package com.kapti.pointsmanager.util;
import com.kapti.client.finance.FinanceFactory;
import com.kapti.client.finance.Quote;
import com.kapti.client.user.PortfolioFactory;
import com.kapti.client.user.Transaction;
import com.kapti.client.user.Transaction.Type;
import com.kapti.client.user.TransactionFactory;
import com.kapti.client.user.User;
import com.kapti.client.user.UserSecurity;
import com.kapti.exceptions.StockPlayException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
/**
* Hulpklasse om de berekening van winst en winstpercentage te berekenen voor
* een gebruiker.
*
* @author Dieter
*/
public class Profit {
private double profit = 0;
private double profitPercentage = 0;
private int amount = 0; //Hoeveelheid aandelen (om gewicht van effecten in rekening te brengen bij percentageberekening)
private User user;
public Profit(User user) throws StockPlayException {
this.user = user;
//Vanaf het huidig tijdstip...
GregorianCalendar eindTijd = new GregorianCalendar();
eindTijd.setTime(new Date());
//... tot 24 uur geleden
GregorianCalendar startTijd = new GregorianCalendar();
startTijd.setTime(new Date());
startTijd.add(Calendar.DATE, -1);
SimpleDateFormat formaat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
//Portfolio en transactie van vandaag ophalen
Collection<UserSecurity> portfolio = PortfolioFactory.getInstance().getPortfolioByUser(user);
Collection<Transaction> transactions = TransactionFactory.getInstance().getTransactionByFilter( "USERID == '" +
user.getId() +
"' && TIMEST <= '" +
formaat.format(eindTijd.getTime()) +
"'d && TIMEST >= '" +
formaat.format(startTijd.getTime()) +
"'d");
//Collectie omzetten naar twee HashMaps met de BUY/SELL transacties
HashMap<Integer, Transaction> buyTransactions = getTransactionsMap(transactions, Type.BUY);
HashMap<Integer, Transaction> sellTransactions = getTransactionsMap(transactions, Type.SELL);
//Portfolio zetten we ook om makkelijk te kunnen zoeken op ISIN
HashMap<String, UserSecurity> portfolioMap = getPortfolioMap(portfolio);
//Winst berekenen van de koop/verkooporders die bij elkaar horen
koopVerkoopWinst(buyTransactions, sellTransactions);
//Resterende kooporders (die aangekocht zijn in de loop van de dag) berekenen
koopWinst(buyTransactions, portfolioMap);
//Resterende verkooporders (die verkocht zijn in de loop van de dag) berekenen
verkoopWinst(sellTransactions);
//Winst op bestaande portfolio berekenen
portfolioWinst(portfolioMap);
}
/*
* GETTERS
*/
public User getUser() {
return user;
}
public double getProfit() {
return profit;
}
public double getProfitPercentage() {
return profitPercentage;
}
/*
* WINSTBERKENINGEN
*/
private void koopVerkoopWinst(HashMap<Integer, Transaction> buyTransactions,
HashMap<Integer, Transaction> sellTransactions) {
//Buytransactions overlopen en kijken welke hiervan al reeds verkocht zijn
//Van deze berekenen we de winst die in deze periode is gemaakt
for(Integer buyTransactionId : buyTransactions.keySet()) {
Transaction buy = buyTransactions.get(buyTransactionId);
//Alle SELL transacties overlopen
for(Integer sellTransactionId : sellTransactions.keySet()) {
Transaction sell = sellTransactions.get(sellTransactionId);
//Controleren ofdat het over dezelfde ISIN gaat en ofdat SELL wel na de BUY kwam
if(sell.getSecurity().getISIN().equals(buy.getSecurity().getISIN())
&& sell.getTime().after(buy.getTime())) {
//Als we minder of evenveel kochten als verkochten, dan zetten we SELL op 0
if(sell.getAmount() <= buy.getAmount()) {
profit += (sell.getPrice() - buy.getPrice()) * sell.getAmount();
//Winstpercentage herrekenen (rekening houden met gewichten van de aandelen)
profitPercentage = ( amount * profitPercentage + sell.getAmount() * (sell.getPrice()-buy.getPrice())/buy.getPrice() )
/ ( amount + sell.getAmount() );
amount += sell.getAmount();
buy.setAmount( buy.getAmount() - sell.getAmount() );
sell.setAmount(0);
}
//Anders zetten we BUY op 0 en herrekenen SELL
else {
//Winst bijtellen
profit += (sell.getPrice() - buy.getPrice()) * (sell.getAmount() - buy.getAmount());
profitPercentage = ( amount * profitPercentage + sell.getAmount() * (sell.getPrice()-buy.getPrice())/buy.getPrice() )
/ ( amount + (sell.getAmount() - buy.getAmount()) );
amount += sell.getAmount() - buy.getAmount();
sell.setAmount( sell.getAmount() - buy.getAmount() );
buy.setAmount(0);
}
}
}
//Sell transacties met amount 0 worden verwijderd
Iterator<Integer> sellIterator = sellTransactions.keySet().iterator();
while(sellIterator.hasNext()) {
int sellId = sellIterator.next();
if(sellTransactions.get(sellId).getAmount() == 0)
sellIterator.remove();
}
}
//Buy transactions die leeg zijn wegsmijten
Iterator<Integer> buyIterator = sellTransactions.keySet().iterator();
while(buyIterator.hasNext()) {
int buyId = buyIterator.next();
if(buyTransactions.get(buyId).getAmount() == 0)
buyIterator.remove();
}
}
private void koopWinst(HashMap<Integer, Transaction> buyTransactions, HashMap<String, UserSecurity> portfolio) throws StockPlayException {
for(Integer buyTransactionId : buyTransactions.keySet()) {
Transaction transaction = buyTransactions.get(buyTransactionId);
Quote latestQuote = FinanceFactory.getInstance().getLatestQuoteFromSecurity(transaction.getSecurity());
//Portfolio herrekenen zodat aangekocht securities in deze periode niet dubbel gerekend worden
if(portfolio.containsKey(transaction.getSecurity().getISIN())) {
UserSecurity userSecurity = portfolio.get(transaction.getSecurity().getISIN());
userSecurity.setAmount( userSecurity.getAmount() - transaction.getAmount() );
}
profit += (latestQuote.getPrice() - transaction.getPrice()) * transaction.getAmount();
profitPercentage = ( amount * profitPercentage + transaction.getAmount() * (latestQuote.getPrice()-transaction.getPrice())/transaction.getPrice() )
/ ( amount + transaction.getAmount() );
amount += transaction.getAmount();
}
}
private void verkoopWinst(HashMap<Integer, Transaction> sellTransactions) throws StockPlayException {
for(Integer sellTransactionId : sellTransactions.keySet()) {
Transaction transaction = sellTransactions.get(sellTransactionId);
Quote latestQuote = FinanceFactory.getInstance().getLatestQuoteFromSecurity(transaction.getSecurity());
profit += (transaction.getPrice() - latestQuote.getOpen()) * transaction.getAmount();
profitPercentage = ( amount * profitPercentage + transaction.getAmount() * (transaction.getPrice()-latestQuote.getPrice())/transaction.getPrice() )
/ ( amount + transaction.getAmount() );
amount += transaction.getAmount();
}
}
private void portfolioWinst(HashMap<String, UserSecurity> portfolio) throws StockPlayException {
for(String isin : portfolio.keySet()) {
UserSecurity userSecurity = portfolio.get(isin);
Quote latestQuote = FinanceFactory.getInstance().getLatestQuoteFromSecurity(userSecurity.getSecurity());
profit += (latestQuote.getPrice() - latestQuote.getOpen()) * userSecurity.getAmount();
profitPercentage = ( amount * profitPercentage + userSecurity.getAmount() * (latestQuote.getPrice() - latestQuote.getOpen())/latestQuote.getOpen() )
/ ( amount + userSecurity.getAmount() );
amount += userSecurity.getAmount();
}
}
/*
* CONVERSIE
*/
private HashMap<Integer, Transaction> getTransactionsMap(Collection<Transaction> transactions, Type type) {
HashMap<Integer, Transaction> transactionsMap = new HashMap<Integer, Transaction>();
Iterator<Transaction> iterator = transactions.iterator();
while(iterator.hasNext()) {
Transaction transaction = iterator.next();
if(transaction.getType() == type)
transactionsMap.put(transaction.getId(), transaction);
}
return transactionsMap;
}
private HashMap<String, UserSecurity> getPortfolioMap(Collection<UserSecurity> portfolio) {
HashMap<String, UserSecurity> portfolioMap = new HashMap<String, UserSecurity>();
Iterator<UserSecurity> iterator = portfolio.iterator();
while(iterator.hasNext()) {
UserSecurity userSecurity = iterator.next();
portfolioMap.put(userSecurity.getSecurity().getISIN(), userSecurity);
}
return portfolioMap;
}
}