fzaker
2/6/2013 - 12:50 PM

RateOfReturnService.groovy

<%@ page import="fundmanagement.reports.RateOfReturn" %>
<rg:grid domainClass="${RateOfReturn}" maxColumns="14" showFirstColumn="false" footerRow="true" showAllRows="true" width="2000px"
         columnProperties="${[valueAfterCashFlow: [width: 150]]}"
         source="${[service: "rateOfReturn", method: "report",
         params: [clientId: params.client.id,
                fromDate_year:params.fromDate_year, fromDate_month:params.fromDate_month, fromDate_day:params.fromDate_day,
                toDate_year:params.toDate_year, toDate_month:params.toDate_month, toDate_day:params.toDate_day]]}"
/>
package fundmanagement.reports

class RateOfReturn {
    String transactionType
    String symbol
    Integer unitCount
    Double unitPrice
    Double sum
    Date transactionDate
    Double commision
    Integer dayCount
    Double dayRatio
    Double cashFlow
    Double value
    Double valueAfterCashFlow
    Double timeRate

    // Important!
    static mapWith = "none"

    static constraints = {
        transactionType()
        symbol()
        unitCount()
        unitPrice()
        sum()
        transactionDate()
        commision()
        dayCount()
        dayRatio()
        cashFlow()
        value()
        valueAfterCashFlow()
        timeRate()
    }
}
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
    }
}