package org.cryptocoinpartners.module; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Singleton; import javax.persistence.Transient; import org.cryptocoinpartners.enumeration.TransactionType; import org.cryptocoinpartners.schema.Amount; import org.cryptocoinpartners.schema.Asset; import org.cryptocoinpartners.schema.DecimalAmount; import org.cryptocoinpartners.schema.DiscreteAmount; import org.cryptocoinpartners.schema.Exchange; import org.cryptocoinpartners.schema.Fill; import org.cryptocoinpartners.schema.Listing; import org.cryptocoinpartners.schema.Market; import org.cryptocoinpartners.schema.Offer; import org.cryptocoinpartners.schema.Portfolio; import org.cryptocoinpartners.schema.Position; import org.cryptocoinpartners.schema.RemoteEvent; import org.cryptocoinpartners.schema.Trade; import org.cryptocoinpartners.schema.Transaction; import org.cryptocoinpartners.service.PortfolioService; import org.cryptocoinpartners.service.PortfolioServiceException; import org.cryptocoinpartners.service.QuoteService; import org.cryptocoinpartners.util.FeesUtil; import org.cryptocoinpartners.util.Remainder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.espertech.esper.client.deploy.DeploymentException; import com.espertech.esper.client.deploy.ParseException; /** * This depends on a QuoteService being attached to the Context first. * * @author Tim Olson */ @Singleton @SuppressWarnings("UnusedDeclaration") public class BasicPortfolioService implements PortfolioService { private final ConcurrentHashMap<Asset, Amount> allPnLs; private static Object lock = new Object(); public BasicPortfolioService(Portfolio portfolio) { this.addPortfolio(portfolio); this.allPnLs = new ConcurrentHashMap<Asset, Amount>(); } public BasicPortfolioService() { // this.portfolio = new Portfolio(); // this.portfolioService = new BasicPortfolioService(portfolio); this.allPnLs = new ConcurrentHashMap<Asset, Amount>(); } @Override public void init() { findPositions(); } private void findPositions() { // String queryPortfolioStr = "select pf from Portfolio pf"; // List<Portfolio> portfolios = PersistUtil.queryList(Portfolio.class, queryPortfolioStr, null); log.debug("Loading Portfolios:" + portfolios.toString()); List<Position> emptyPositions = Collections.synchronizedList(new ArrayList<Position>()); for (Portfolio portfolio : portfolios) { // String queryStr = "select p from Position p join fetch p.fills f join fetch p.portfolio po where f.openVolumeCount!=0 and po = ?1 group by p"; // String queryStr = "select p from Position p where f.openVolumeCount!=0 and po = ?1 group by p"; // String queryStr = "select p from Position p where p.portfolio = ?1"; //EntityGraph graph = EM.getEnityManager().getEntityGraph("graph.Position.fills"); // Map hints = new HashMap(); // hints.put("javax.persistence.fetchgraph", "graph.Position.fills"); // hints.put("javax.persistence.fetchgraph", "graph.Position.portfolio"); // List<Position> positions = EM.queryList(Position.class, queryStr, hints, portfolio); List<Fill> fills = new ArrayList<Fill>(); log.debug("Loading Positions:" + portfolio.getPositions().toString()); for (Position position : portfolio.getPositions()) { if (position == null) continue; context.getInjector().injectMembers(position); if (!position.hasFills()) { emptyPositions.add(position); continue; } // position.getDao(localPositionDao); // portfolio.addPosition(position); //position.setPortfolio(portfolio); // log.debug("Loading Fills:" + position.getFills().toString()); for (Fill fill : position.getFills()) { if (fill == null) continue; // Map fillHints = new HashMap(); // UUID portfolioID = EM.queryOne(UUID.class, queryStr, portfolioName); //fillHints.put("javax.persistence.fetchgraph", "fillsWithChildOrders"); //Fill detailedFill = EM.namedQueryZeroOne(Fill.class, "Fills.findFillsById", fillHints, fill.getId()); context.getInjector().injectMembers(fill); if (!fill.getOpenVolume().isZero()) { fills.add(fill); } // portfolio.merge(fill); } } portfolio.removePositions(emptyPositions); for (Position position : emptyPositions) { // EntityBase update = position.refresh(); context.getInjector().injectMembers(position); position.delete(); } Collections.sort(fills, timeReceivedComparator); for (Fill fill : fills) { log.trace(this.getClass().getSimpleName() + ": findPositions merging fill for " + fill); portfolio.merge(fill); } } log.trace("completed loading of existing portfolio"); } private static final Comparator<RemoteEvent> timeReceivedComparator = new Comparator<RemoteEvent>() { @Override public int compare(RemoteEvent event, RemoteEvent event2) { return event.getTimeReceived().compareTo(event2.getTimeReceived()); } }; @Override @Nullable public Collection<Position> getPositions() { Collection<Position> AllPositions = new ArrayList<Position>(); for (Portfolio portfolio : getPortfolios()) { for (Position position : portfolio.getNetPositions()) AllPositions.add(position); } return AllPositions; } @Transient public Context getContext() { return context; } protected void setContext(Context context) { this.context = context; } @Override @Nullable public ConcurrentHashMap<Asset, Amount> getRealisedPnLs() { ConcurrentHashMap<Asset, Amount> AllRealisedPnLs = new ConcurrentHashMap<Asset, Amount>(); for (Portfolio portfolio : getPortfolios()) { for (Asset asset : portfolio.getRealisedPnLs().keySet()) if (AllRealisedPnLs.get(asset) == null) AllRealisedPnLs.put(asset, portfolio.getRealisedPnLs().get(asset)); else AllRealisedPnLs.get(asset).plus(portfolio.getRealisedPnLs().get(asset)); } return AllRealisedPnLs; } @Override @Nullable public ConcurrentHashMap<Asset, ConcurrentHashMap<Exchange, ConcurrentHashMap<Listing, Amount>>> getRealisedPnLByMarket() { ConcurrentHashMap<Asset, ConcurrentHashMap<Exchange, ConcurrentHashMap<Listing, Amount>>> AllRealisedPnL = new ConcurrentHashMap<Asset, ConcurrentHashMap<Exchange, ConcurrentHashMap<Listing, Amount>>>(); for (Portfolio portfolio : getPortfolios()) { for (Asset asset : portfolio.getRealisedPnL().keySet()) if (AllRealisedPnL.get(asset) == null) AllRealisedPnL.put(asset, portfolio.getRealisedPnL().get(asset)); // else // AllRealisedPnL.get(asset).plus(portfolio.getRealisedPnL().get(asset)); } return AllRealisedPnL; } public DiscreteAmount getLongPosition(Asset asset, Exchange exchange) { return null; } public DiscreteAmount getShortPosition(Asset asset, Exchange exchange) { return null; } @Override public DiscreteAmount getNetPosition(Asset asset, Exchange exchange) { return null; } @Override @Nullable public ArrayList<Position> getPositions(Exchange exchange) { // TODO Auto-generated method stub return null; } @Override @Nullable public Collection<Position> getPositions(Asset asset, Exchange exchange) { // return portfolio.getPositions(asset, exchange); return null; } @Override public DiscreteAmount getLastTrade() { List<Object> events = null; try { events = context.loadStatementByName("GET_LAST_TICK"); if (events.size() > 0) { Trade trade = ((Trade) events.get(events.size() - 1)); return (trade.getPrice()); } } catch (ParseException | DeploymentException | IOException e) { // TODO Auto-generated catch block log.error("Threw a Execption, full stack trace follows:", e); e.printStackTrace(); } return null; } @Override @Transient public ConcurrentHashMap<Asset, Amount> getAvailableBalances() { // so we need to get the cash balances // then we will add to it the avg price x quantity of the open position Amount availableBalance = DecimalAmount.ZERO; ConcurrentHashMap<Asset, Amount> availableBalances = new ConcurrentHashMap<>(); for (Transaction transaction : getTrades()) { if (availableBalances.get(transaction.getAsset()) != null) { availableBalance = availableBalances.get(transaction.getAsset()); } Amount tranCost = transaction.getCost(); availableBalance = availableBalance.plus(tranCost); availableBalances.put(transaction.getAsset(), availableBalance); } return availableBalances; } @Override @Transient public Map<Asset, Amount> getCashBalances() { //synchronized (lock) { if (balances == null || balances.isEmpty()) return getCurrentCashBalances(true); else // synchronized (lock) { return getCurrentCashBalances(false); // } } @Transient private Map<Asset, Amount> getCurrentCashBalances(boolean reset) { // if (reset) { // sum of all transactions that belongs to this strategy balances = new ConcurrentHashMap<Asset, Amount>(); ConcurrentHashMap<Asset, Amount> bals = new ConcurrentHashMap<Asset, Amount>(); // balances.hashCode(); Amount balance = DecimalAmount.ZERO; // tradesHasgetTrades().hashCode() Iterator<Transaction> itt = getTrades().iterator(); while (itt.hasNext()) { balance = DecimalAmount.ZERO; Transaction transaction = itt.next(); if (bals.get(transaction.getAsset()) != null) { balance = bals.get(transaction.getAsset()); } Amount tranCost = transaction.getCost(); balance = balance.plus(tranCost); bals.put(transaction.getAsset(), balance); } // plus part of all cashFlows //Amount cashFlows = new DiscreteAmount(0, portfolio.getBaseAsset().getBasis()); Iterator<Transaction> itc = getCashFlows().iterator(); while (itc.hasNext()) { Amount cashFlows = DecimalAmount.ZERO; Transaction cashFlowTransaction = itc.next(); if (bals.get(cashFlowTransaction.getCurrency()) != null) { cashFlows = bals.get(cashFlowTransaction.getCurrency()); } Amount tranCost = cashFlowTransaction.getCost(); cashFlows = cashFlows.plus(tranCost); bals.put(cashFlowTransaction.getCurrency(), cashFlows); } //Amount amount = balance.plus(cashFlows); Iterator<Asset> it = getRealisedPnLByMarket().keySet().iterator(); while (it.hasNext()) { Asset asset = it.next(); Iterator<Exchange> ite = getRealisedPnLByMarket().get(asset).keySet().iterator(); while (ite.hasNext()) { Exchange exchange = ite.next(); Iterator<Listing> itm = getRealisedPnLByMarket().get(asset).get(exchange).keySet().iterator(); while (itm.hasNext()) { Listing listing = itm.next(); Market market = context.getInjector().getInstance(Market.class).findOrCreate(exchange, listing); Amount realisedPnL = getRealisedPnLByMarket().get(asset).get(exchange).get(listing); // need to change this to the market and check the margin. if (!realisedPnL.isZero()) { if (bals.get(asset) != null) { balance = bals.get(asset); } balance = balance.plus(realisedPnL); bals.put(asset, balance); } } } } Amount transferCredits = DecimalAmount.ZERO; Amount transferDebits = DecimalAmount.ZERO; Iterator<Transaction> itr = getTransfers().iterator(); while (itr.hasNext()) { Transaction transactionTransaction = itr.next(); if (bals.get(transactionTransaction.getCurrency()) != null) { transferDebits = bals.get(transactionTransaction.getCurrency()); } if (bals.get(transactionTransaction.getAsset()) != null) { transferCredits = bals.get(transactionTransaction.getAsset()); } Amount tranCost = transactionTransaction.getCost(); transferCredits = transferCredits.plus(tranCost); transferDebits = transferDebits.plus(transactionTransaction.getAmount()); bals.put(transactionTransaction.getCurrency(), transferDebits); bals.put(transactionTransaction.getAsset(), transferCredits); } // balances = bals; // } // } return balances; } @Transient @SuppressWarnings("null") private List<Transaction> getCashFlows() { // return all CREDIT,DEBIT,INTREST,FEES and REALISED PnL ArrayList<Transaction> cashFlows = new ArrayList<>(); for (Portfolio portfolio : getPortfolios()) { for (Transaction transaction : portfolio.getTransactions()) { if (transaction.getType() == (TransactionType.CREDIT) || transaction.getType() == (TransactionType.DEBIT) || transaction.getType() == (TransactionType.INTREST) || transaction.getType() == (TransactionType.FEES)) { cashFlows.add(transaction); } } } return cashFlows; } private List<Transaction> getTransfers() { // return all CREDIT,DEBIT,INTREST,FEES and REALISED PnL ArrayList<Transaction> transfers = new ArrayList<>(); for (Portfolio portfolio : getPortfolios()) { for (Transaction transaction : portfolio.getTransactions()) { if (transaction.getType() == (TransactionType.REBALANCE)) { transfers.add(transaction); } } } return transfers; } @Transient @SuppressWarnings("null") private List<Transaction> getTrades() { //return all BUY and SELL ArrayList<Transaction> trades = new ArrayList<>(); // int transHashcode = portfolio.getTransactions().hashCode(); // log.info("transaction hascode" + transHashcode); for (Portfolio portfolio : getPortfolios()) { for (Transaction transaction : portfolio.getTransactions()) { if (transaction.getType() == (TransactionType.BUY) || transaction.getType() == (TransactionType.SELL)) { trades.add(transaction); } } // transactionsHashCode = portfolio.getTransactions().hashCode(); } return trades; } @Override @Transient public DiscreteAmount getMarketPrice(Position postion) { if (postion.isOpen()) { if (postion.isShort()) { @SuppressWarnings("ConstantConditions") DiscreteAmount price = quotes.getLastAskForMarket(postion.getMarket()).getPrice(); return price; } else { @SuppressWarnings("ConstantConditions") DiscreteAmount price = quotes.getLastBidForMarket(postion.getMarket()).getPrice(); return price; } } else { return new DiscreteAmount(0, postion.getMarket().getVolumeBasis()); } } @Override @Transient public Amount getMarketValue(Position position) { if (position.isOpen()) { Amount marketPrice = getMarketPrice(position); if (position.getMarket().getTradedCurrency().equals(position.getMarket().getBase())) marketPrice = marketPrice.invert(); return (position.getVolume().times(marketPrice, Remainder.ROUND_EVEN)).times(position.getMarket().getContractSize(), Remainder.ROUND_EVEN); } else { return new DiscreteAmount(0, position.getMarket().getVolumeBasis()); } } @Override @Transient public Amount getUnrealisedPnL(Position position) { //have to invert her Amount marketPrice = position.getAvgPrice(); Amount avgPrice = getMarketPrice(position); if (position.getMarket().getTradedCurrency().equals(position.getMarket().getBase())) { avgPrice = (position.getAvgPrice()).invert(); marketPrice = getMarketPrice(position).invert(); } return (position.isFlat()) ? new DiscreteAmount(0, position.getMarket().getVolumeBasis()) : ((avgPrice.minus(marketPrice)).times(position.getVolume(), Remainder.ROUND_EVEN)).times(position.getMarket().getContractSize(), Remainder.ROUND_EVEN); } @Override @Transient public ConcurrentHashMap<Asset, Amount> getMarketValues() { Amount marketValue = DecimalAmount.ZERO; //Amount marketValue = new DiscreteAmount(0, 0.01); ConcurrentHashMap<Asset, Amount> marketValues = new ConcurrentHashMap<>(); //portfolio.getPositions().keySet() for (Portfolio portfolio : getPortfolios()) { for (Position position : portfolio.getNetPositions()) { if (position.isOpen()) { if (marketValues.get(position.getAsset()) != null) { marketValue = marketValues.get(position.getAsset()); } marketValue = marketValue.plus(getMarketValue(position)); marketValues.put(position.getMarket().getTradedCurrency(), marketValue); } } } return marketValues; } @Override @Transient public ConcurrentHashMap<Asset, Amount> getUnrealisedPnLs() { Amount unrealisedPnL = DecimalAmount.ZERO; //Amount marketValue = new DiscreteAmount(0, 0.01); ConcurrentHashMap<Asset, Amount> unrealisedPnLs = new ConcurrentHashMap<>(); //portfolio.getPositions().keySet() for (Portfolio portfolio : getPortfolios()) { for (Position position : portfolio.getNetPositions()) { if (position.isOpen()) { if (unrealisedPnLs.get(position.getAsset()) != null) { unrealisedPnL = unrealisedPnLs.get(position.getAsset()); } unrealisedPnL = unrealisedPnL.plus(getUnrealisedPnL(position)); unrealisedPnLs.put(position.getMarket().getTradedCurrency(), unrealisedPnL); } } } return unrealisedPnLs; } @Override @Transient public Amount getBaseMarketValue(Asset quoteAsset) { //Amount marketValue; //ConcurrentHashMap<Asset, Amount> marketValues = new ConcurrentHashMap<>(); //portfolio.get //Asset quoteAsset = list.getBase(); //Asset baseAsset=new Asset(); // Amount baseMarketValue = new DiscreteAmount(0, 0.01); Amount baseMarketValue = DecimalAmount.ZERO; ConcurrentHashMap<Asset, Amount> marketValues = getMarketValues(); for (Asset baseAsset : marketValues.keySet()) { Listing listing = Listing.forPair(baseAsset, quoteAsset); Offer rate = quotes.getImpliedBestAskForListing(listing); baseMarketValue = baseMarketValue.plus(marketValues.get(baseAsset).times(rate.getPrice(), Remainder.ROUND_EVEN)); } return baseMarketValue; } @Override @Transient public Amount getMarketValue(Asset quoteAsset) { //Amount marketValue; //ConcurrentHashMap<Asset, Amount> marketValues = new ConcurrentHashMap<>(); //portfolio.get //Asset quoteAsset = list.getBase(); //Asset baseAsset=new Asset(); // Amount baseMarketValue = new DiscreteAmount(0, 0.01); Amount marketValue = DecimalAmount.ZERO; ConcurrentHashMap<Asset, Amount> marketValues = getMarketValues(); for (Asset baseAsset : marketValues.keySet()) { if (baseAsset.equals(quoteAsset)) { marketValue = marketValue.plus(marketValues.get(baseAsset)); } } return marketValue; } @Override @Transient public Amount getBaseUnrealisedPnL(Asset quoteAsset) { //Amount marketValue; //ConcurrentHashMap<Asset, Amount> marketValues = new ConcurrentHashMap<>(); //portfolio.get //Asset quoteAsset = list.getBase(); //Asset baseAsset=new Asset(); // Amount baseMarketValue = new DiscreteAmount(0, 0.01); Amount baseUnrealisedPnL = DecimalAmount.ZERO; ConcurrentHashMap<Asset, Amount> unrealisedPnLs = getUnrealisedPnLs(); for (Asset baseAsset : unrealisedPnLs.keySet()) { Listing listing = Listing.forPair(baseAsset, quoteAsset); Offer rate = quotes.getImpliedBestAskForListing(listing); baseUnrealisedPnL = baseUnrealisedPnL.plus(unrealisedPnLs.get(baseAsset).times(rate.getPrice(), Remainder.ROUND_EVEN)); } return baseUnrealisedPnL; } @Override @Transient public Amount getUnrealisedPnL(Asset quoteAsset) { //Amount marketValue; //ConcurrentHashMap<Asset, Amount> marketValues = new ConcurrentHashMap<>(); //portfolio.get //Asset quoteAsset = list.getBase(); //Asset baseAsset=new Asset(); // Amount baseMarketValue = new DiscreteAmount(0, 0.01); Amount unrealisedPnL = DecimalAmount.ZERO; ConcurrentHashMap<Asset, Amount> unrealisedPnLs = getUnrealisedPnLs(); for (Asset baseAsset : unrealisedPnLs.keySet()) { if (baseAsset.equals(quoteAsset)) { unrealisedPnL = unrealisedPnL.plus(unrealisedPnLs.get(baseAsset)); } } return unrealisedPnL; } @Override @Transient public Amount getBaseRealisedPnL(Asset quoteAsset) { //Listing list = Listing.forSymbol(config.getString("base.symbol", "USD")); //Asset quoteAsset = list.getBase(); //Asset baseAsset=new Asset(); Amount baseRealisedPnL = DecimalAmount.ZERO; //Amount baseCashBalance = new DiscreteAmount(0, portfolio.getBaseAsset().getBasis()); ConcurrentHashMap<Asset, Amount> realisedPnLs = getRealisedPnLs(); for (Asset baseAsset : realisedPnLs.keySet()) { Listing listing = Listing.forPair(baseAsset, quoteAsset); Offer rate = quotes.getImpliedBestAskForListing(listing); Amount localPnL = realisedPnLs.get(baseAsset); Amount basePnL = localPnL.times(rate.getPrice(), Remainder.ROUND_EVEN); baseRealisedPnL = baseRealisedPnL.plus(basePnL); } return baseRealisedPnL; } @Override @Transient public Amount getRealisedPnL(Asset quoteAsset) { //Listing list = Listing.forSymbol(config.getString("base.symbol", "USD")); //Asset quoteAsset = list.getBase(); //Asset baseAsset=new Asset(); Amount realisedPnL = DecimalAmount.ZERO; //Amount baseCashBalance = new DiscreteAmount(0, portfolio.getBaseAsset().getBasis()); ConcurrentHashMap<Asset, Amount> realisedPnLs = getRealisedPnLs(); for (Asset baseAsset : realisedPnLs.keySet()) { if (baseAsset.equals(quoteAsset)) { Amount localPnL = realisedPnLs.get(baseAsset); realisedPnL = realisedPnL.plus(localPnL); } } return realisedPnL; } @Override @Transient public Amount getCashBalance(Asset quoteAsset) { Amount cashBalance = DecimalAmount.ZERO; Map<Asset, Amount> cashBalances = getCashBalances(); for (Asset baseAsset : cashBalances.keySet()) { if (baseAsset.equals(quoteAsset)) { // Listing listing = Listing.forPair(baseAsset, quoteAsset); //Offer rate = quotes.getImpliedBestAskForListing(listing); Amount localBalance = cashBalances.get(baseAsset); //Amount baseBalance = localBalance.times(rate.getPrice(), Remainder.ROUND_EVEN); cashBalance = cashBalance.plus(localBalance); } } return cashBalance; } @Override @Transient public Amount getBaseCashBalance(Asset quoteAsset) { Amount cashBalance = DecimalAmount.ZERO; Map<Asset, Amount> cashBalances = getCashBalances(); for (Asset baseAsset : cashBalances.keySet()) { Listing listing = Listing.forPair(baseAsset, quoteAsset); Offer rate = quotes.getImpliedBestAskForListing(listing); Amount localBalance = cashBalances.get(baseAsset); Amount baseBalance = localBalance.times(rate.getPrice(), Remainder.ROUND_EVEN); cashBalance = cashBalance.plus(baseBalance); } return cashBalance; } @Override @Transient public Amount getAvailableBalance(Asset quoteAsset) { Amount marginBalance = DecimalAmount.ZERO; ConcurrentHashMap<Asset, Amount> margins = getMargins(quoteAsset); for (Asset baseAsset : margins.keySet()) { Listing listing = Listing.forPair(baseAsset, quoteAsset); //Offer rate = quotes.getImpliedBestAskForListing(listing); Amount localMargin = margins.get(baseAsset); //Amount baseMargin = localMargin.times(rate.getPrice(), Remainder.ROUND_EVEN); marginBalance = marginBalance.plus(localMargin); } return getCashBalance(quoteAsset).plus(marginBalance); } @Override @Transient public Amount getAvailableBaseBalance(Asset quoteAsset) { Amount marginBalance = DecimalAmount.ZERO; ConcurrentHashMap<Asset, Amount> margins = getMargins(quoteAsset); for (Asset baseAsset : margins.keySet()) { Listing listing = Listing.forPair(baseAsset, quoteAsset); Offer rate = quotes.getImpliedBestAskForListing(listing); Amount localMargin = margins.get(baseAsset); Amount baseMargin = localMargin.times(rate.getPrice(), Remainder.ROUND_EVEN); marginBalance = marginBalance.plus(baseMargin); } return getBaseCashBalance(quoteAsset).plus(marginBalance); } @Transient private ConcurrentHashMap<Asset, Amount> getMargins(Asset quoteAsset) { Amount baseAvailableBalance = DecimalAmount.ZERO; Amount totalMargin = DecimalAmount.ZERO; //Amount baseCashBalance = getCashBalance(quoteAsset); ConcurrentHashMap<Asset, Amount> margins = new ConcurrentHashMap<Asset, Amount>(); for (Portfolio portfolio : getPortfolios()) { for (Position position : portfolio.getNetPositions()) { Asset baseAsset = position.getMarket().getTradedCurrency(); if (position.isOpen() && baseAsset.equals(quoteAsset)) { // calucate total margin if (margins.get(baseAsset) != null) totalMargin = margins.get(baseAsset); totalMargin = totalMargin.plus(FeesUtil.getMargin(position)); } margins.put(baseAsset, totalMargin); } } return margins; } // public void CreateTransaction(Portfolio portfolio, Exchange exchange, Asset asset, TransactionType type, Amount amount, Amount price) { // Transaction transaction = new Transaction(portfolio, exchange, asset, type, amount, price); // // context.route(transaction); // transaction.persit(); // } @Override public void resetBalances() { // getCurrentCashBalances(true); } @Override public void exitPosition(Position position) throws Exception { reducePosition(position, (position.getVolume().abs())); } @Override public void reducePosition(final Position position, final Amount amount) { try { this.handleReducePosition(position, amount); } catch (Throwable th) { throw new PortfolioServiceException("Error performing 'PositionService.reducePosition(int positionId, long quantity)' --> " + th, th); } } @Override public void handleReducePosition(Position position, Amount amount) throws Exception { //TODO remove subsrcption } @Override public void handleSetMargin(Position position) throws Exception { //TODO manage setting and mainuplating margin } @Override public void handleSetMargins() throws Exception { //TODO manage setting and mainuplating margin } @Inject protected transient Context context; @Inject protected transient QuoteService quotes; protected static Logger log = LoggerFactory.getLogger("org.cryptocoinpartners.portfolioService"); private static int transactionsHashCode; private static int tradesHashCode; private static int marginsHashCode; private static Map<Asset, Amount> balances; private Collection<Portfolio> portfolios; @Override public Collection<Portfolio> getPortfolios() { if (portfolios == null) portfolios = new ArrayList<Portfolio>(); // synchronized (lock) { return portfolios; // } } @Override public void setPortfolios(Collection<Portfolio> portfolios) { this.portfolios = portfolios; } @Override public void addPortfolio(Portfolio portfolio) { // synchronized (lock) { getPortfolios().add(portfolio); //} } }