package fundmanagement
import fundmanagement.transactions.*
import fundmanagement.reports.RateOfReturn
class RateOfReturnService {
def messageSource
def symbolSynchronizationService
def report(params) {
def client
if(params.client)
client = Client.findById(params.client.id)
else
client = Client.findById(params.clientId)
def lastDay = new Date()
def portfolioTransactions = PortfolioTransaction.findAllByClient(client).sort { a, b -> a.transactionDate <=> b.transactionDate }
if(params.fromDate_year)
{
def fromDate = Date.parse("yyyy/MM/dd", params.fromDate_year + "/" + params.fromDate_month + "/" + params.fromDate_day)
portfolioTransactions = portfolioTransactions.findAll {item -> item.transactionDate >= fromDate}
}
if(params.toDate_year)
{
def toDate = Date.parse("yyyy/MM/dd", params.toDate_year + "/" + params.toDate_month + "/" + params.toDate_day)
portfolioTransactions = portfolioTransactions.findAll {item -> item.transactionDate <= toDate}
lastDay = toDate
}
def list = []
def locale = new Locale("en")
def maxDays = 1
def count = 0
def totalCashProperty = 0
def portfolioProperties = [:]
portfolioTransactions.each {
def rateOfReturn = new RateOfReturn()
rateOfReturn.id = ++count
rateOfReturn.transactionType = messageSource.getMessage("portfolioTransaction.transactionType.${it.transactionType}", null, locale)
rateOfReturn.symbol = it.symbol.title
rateOfReturn.unitCount = it.unitCount
rateOfReturn.unitPrice = it.unitPrice
rateOfReturn.sum = it.absoluteAmount
rateOfReturn.transactionDate = it.transactionDate
rateOfReturn.commision = it.commision
use(groovy.time.TimeCategory) { x ->
def duration = lastDay - it.transactionDate
rateOfReturn.dayCount = duration.days
if (maxDays < duration.days)
maxDays = duration.days
}
if (it instanceof CashTransaction)
totalCashProperty += it.absoluteAmount
else {
portfolioProperties[it.symbol] = (portfolioProperties[it.symbol.title] ?: 0) + it.signedCount
if (it.transactionType != "init")
totalCashProperty += it.absoluteAmount
}
if (it.transactionType in ["init", "deposit", "withdraw"])
rateOfReturn.cashFlow = it.absoluteAmount
else
rateOfReturn.cashFlow = 0
rateOfReturn.valueAfterCashFlow = totalCashProperty + portfolioValue(portfolioProperties, it.transactionDate)
rateOfReturn.value = rateOfReturn.valueAfterCashFlow - rateOfReturn.cashFlow
list << rateOfReturn
}
def lastRateOfReturn = new RateOfReturn()
lastRateOfReturn.id = ++count
lastRateOfReturn.transactionType = ""
lastRateOfReturn.symbol = ""
lastRateOfReturn.unitCount = 0
lastRateOfReturn.unitPrice = 0
lastRateOfReturn.sum = 0
lastRateOfReturn.transactionDate = lastDay
lastRateOfReturn.commision = 0
lastRateOfReturn.dayCount = 0
lastRateOfReturn.cashFlow = 0
lastRateOfReturn.value = totalCashProperty + portfolioValue(portfolioProperties, lastDay)
lastRateOfReturn.valueAfterCashFlow = lastRateOfReturn.value
list << lastRateOfReturn
list.each { RateOfReturn ror ->
ror.dayRatio = 1.0 * ror.dayCount / maxDays
}
def EMV = lastRateOfReturn.valueAfterCashFlow
def totalCashFlow = list.sum { it.cashFlow }
def weightedCashFlow = list.sum { it.cashFlow * it.dayRatio }
def MWRR = (EMV - totalCashFlow) / weightedCashFlow
def YMWRR = Math.pow(1.0 + MWRR, 365.0 / maxDays) - 1.0
def userdata = [:]
userdata.value = "MWRR=%${String.format("%.2f", 100.0 * MWRR)}"
userdata.valueAfterCashFlow="Yearly MWRR=%${String.format("%.2f", 100.0 * YMWRR)}"
[list: list, userdata: userdata]
}
def portfolioValue(portfolioProperties, dt) {
def val = 0
portfolioProperties.each { key, value ->
def price = symbolSynchronizationService.getSymbolPriceOnDate(key, dt)
val += value * price
}
val
}
}