产量计算

时间:2014-06-25 19:45:39

标签: java math

在我的投资组合应用程序中,我有一个包含股票头衔和投资组合权重的表对于每个股票标题,我正在下载特定时间窗口的价格。现在我正在尝试计算平均投资组合利率。

每日公式:

  

Ypf(d)=(W1 * Y1(d))+(W2 * Y2(d))+ ... +(Wn * Yn(d))

公式组合:

  

(Ypf(1)+ Ypf(2)+ ... + Ypf(dn))/ n

> W1 = weight of 1st stock in table 
> W2 = weight of 2nd stock in table
> Y1 = yield of 1st stock in table
> Y2 = yield of 2nd stock in table
> d = current day n = total days

我被困在这里寻求帮助....

public void calcAvgYield() {
    for (Stock s : pfTable.getItems()) {
        // get list of prices for stock title
        List<Double> vl = s.getValue();
        // new list for calculated yield
        List<Double> yl = null;
        // get weight for stock title
        int w = s.getWeight();
        // get list size
        int i = vl.size()-1;
        // calculate yield for each day and fill new list with results
        while (i > 0) {
            yl.add(((s.getValue().get(i) - s.getValue().get(i-1)) / s.getValue().get(i-1)) * 100);
            i--;
        } 
    }
}

股票类:

public class Stock {

    private final SimpleStringProperty symbol = new SimpleStringProperty();
    private final SimpleIntegerProperty weight = new SimpleIntegerProperty();

    private List<Double> value = new ArrayList<Double>();
    private List<String> date = new ArrayList<String>();

    public String getSymbol() {
        return symbol.get();
    }

    public void setSymbol(String symbol) {
        this.symbol.set(symbol);
    }

    public Integer getWeight() {
        return weight.get();
    }

    public void setWeight(Integer weight) {
        this.weight.set(weight);
    }     

    public List<Double> getValue() {
        return value;
    }

    public void setValue(ArrayList<Double> value) {
        this.value = value;
    } 

}

感谢。

3 个答案:

答案 0 :(得分:1)

Java是一种面向对象的语言。为什么不使用对象和封装来获得更好的优势?我认为你的问题是你没有很好地解决问题。

我希望看到Stock课程,而不是双打榜。 Portfolio会有Map股票,股票对。

Stock可能有Map个日期,值对。

你如何计算重量?它们是Portfolio中的一部分份额吗?

Portfolio通过迭代Map Stocks来计算方法中的当前回报率。

我是这样做的。我认为仍有细微之处需要根据股票数量进行整理,因为您的头寸会随着时间的推移而发展。随着时间的推移,股票和股票的地图不足。但这会给你一个想法。

Stock.java

package stock;

import utils.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Stock abstraction
 * @author Michael
 * @link https://stackoverflow.com/questions/24417246/yield-calculation/24430415
 * @since 6/26/2014 6:22 PM
 */
public class Stock implements Comparable<Stock> {
    private final String symbol;
    private final String companyName;
    private Map<Date, Double> prices;

    public Stock(String symbol, String companyName) {
        if (StringUtils.isBlankOrNull(symbol)) throw new IllegalArgumentException("symbol cannot be blank or null");
        if (StringUtils.isBlankOrNull(companyName)) throw new IllegalArgumentException("company name cannot be blank or null");
        this.symbol = symbol;
        this.companyName = companyName;
        this.prices = new ConcurrentHashMap<Date, Double>();
    }

    public String getSymbol() {
        return symbol;
    }

    public String getCompanyName() {
        return companyName;
    }

    public void addPrice(Date date, double price) {
        if (date == null) throw new IllegalArgumentException("date cannot be null");
        if (price < 0.0) throw new IllegalArgumentException("price cannot be negative");
        this.prices.put(date, price);
    }

    public void removePrice(Date date) {
        if (date != null) {
            this.prices.remove(date);
        }
    }

    public synchronized Double getPrice(Date date) {
        double price = 0.0;
        if (this.prices.containsKey(date)) {
            price = this.prices.get(date);
        } else {
            price = interpolatePrice(date);
        }
        return price;
    }

    private Double interpolatePrice(Date date) {
        double price = 0.0;
        if (this.prices.size() > 0) {
            List<Date> dates = new ArrayList<Date>(this.prices.keySet());
            Collections.sort(dates, new DateComparator());
            if (date.before(dates.get(0))) {
                price = this.prices.get(dates.get(0));
            } else if (date.after(dates.get(dates.size()-1))) {
                price = this.prices.get(dates.get(dates.size()-1));
            } else {
                for (int i = 1; i < dates.size(); ++i) {
                    if (dates.get(i).after(date)) {
                        Date d1 = dates.get(i-1);
                        double p1 = this.prices.get(d1);
                        Date d2 = dates.get(i);
                        double p2 = this.prices.get(d2);
                        double fraction = ((double)(date.getTime()-d1.getTime())/(d2.getTime()-d1.getTime()));
                        price = p1 + fraction*(p2-p1);
                    }
                }
            }
        }
        return price;
    }

    public boolean hasDate(Date date) {
        return this.prices.containsKey(date);
    }

    public int getNumPrices() {
        return this.prices.size();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Stock stock = (Stock) o;

        return symbol.equals(stock.symbol);
    }

    @Override
    public int hashCode() {
        return symbol.hashCode();
    }

    @Override
    public int compareTo(Stock other) {
        return this.symbol.compareTo(other.symbol);
    }

    @Override
    public String toString() {
        return this.symbol;
    }
}

class DateComparator implements Comparator<Date> {
    @Override
    public int compare(Date that, Date another) {
        if (that.before(another)) {
            return -1;
        } else if (that.after(another)) {
            return +1;
        } else {
            return 0;
        }
    }
}

Portfolio.java:

package stock;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Portfolio is a collection of Stocks
 * @author Michael
 * @link https://stackoverflow.com/questions/24417246/yield-calculation/24430415
 * @since 6/26/2014 6:31 PM
 */
public class Portfolio {

    private Map<Stock, Integer> stocks;

    public Portfolio() {
        this.stocks = new ConcurrentHashMap<Stock, Integer>();
    }

    public void addStock(Stock stock, int numShares) {
        if (stock == null) throw new IllegalArgumentException("stock cannot be null");
        this.stocks.put(stock, numShares);
    }

    public void addStock(Stock stock) {
        addStock(stock, 1);
    }

    public void updateShares(Stock stock, int numShares) {
        if (numShares <= 0) throw new IllegalArgumentException("numShares must be greater than zero");
        if (stock != null) {
            this.stocks.put(stock, numShares);
        }
    }

    public void removeStock(Stock stock) {
        if (stock != null) {
            this.stocks.remove(stock);
        }
    }

    public boolean containsSymbol(String symbol) {
        return this.getPortfolioSymbols().contains(symbol);
    }

    public int getNumShares(String symbol) {
        int numShares = 0;
        if (this.getPortfolioSymbols().contains(symbol)) {
            numShares = this.stocks.get(new Stock(symbol, "Dummy Company Name"));
        }
        return numShares;
    }

    public int getNumStocks() {
        return this.stocks.size();
    }

    public List<String> getPortfolioSymbols() {
        List<String> symbols = new ArrayList<String>(this.stocks.size());
        for (Stock stock : stocks.keySet()) {
            symbols.add(stock.getSymbol());
        }
        Collections.sort(symbols);
        return symbols;
    }

    public double calculateValue(Date date) {
        double value = 0.0;
        if (date != null) {
            for (Stock stock : this.stocks.keySet()) {
                value += stock.getPrice(date)*this.stocks.get(stock);
            }
        }
        return value;
    }
}

以下是单元测试Java类的方法。我还为Portfolio编写了一个JUnit测试,但我现在不会发布它。

StockTest.java:

package stock;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * PortfolioTest JUnit test for Portfolio
 * @author Michael
 * @link https://stackoverflow.com/questions/24417246/yield-calculation/24430415
 * @since 6/26/2014 8:33 PM
 */
public class PortfolioTest {

    private static final String DATE_PATTERN = "yyyy-MMM-dd";
    private static final DateFormat DATE_FORMAT;
    private static final double TOLERANCE = 0.001;

    static {
        DATE_FORMAT = new SimpleDateFormat(DATE_PATTERN);
        DATE_FORMAT.setLenient(false);
    }

    private Portfolio portfolio;

    @Before
    public void setUp() throws ParseException {
        this.portfolio = new Portfolio();
        Stock testStock = new Stock("AAPL", "Apple Inc");
        testStock.addPrice(DATE_FORMAT.parse("2014-Jun-02"), 89.807);
        testStock.addPrice(DATE_FORMAT.parse("2014-Jun-04"), 92.117);
        this.portfolio.addStock(testStock, 100);
        testStock = new Stock("ORCL", "Oracle Corporation");
        testStock.addPrice(DATE_FORMAT.parse("2014-Jun-02"), 41.97);
        testStock.addPrice(DATE_FORMAT.parse("2014-Jun-04"), 41.70);
        this.portfolio.addStock(testStock, 1000);
    }

    @Test
    public void testPortfolio_Setup() {
        List<String> expectedSymbols = Arrays.asList("AAPL", "ORCL");
        Assert.assertEquals(expectedSymbols, this.portfolio.getPortfolioSymbols());
        for (String symbol : expectedSymbols) {
            Assert.assertTrue(this.portfolio.containsSymbol(symbol));
        }
        Assert.assertEquals(expectedSymbols.size(), portfolio.getNumStocks());
        Assert.assertFalse(this.portfolio.containsSymbol("UTX"));
    }

    @Test
    public void testRemoveStock_ContainsStock() {
        int expectedSize = 2;
        Assert.assertEquals(expectedSize, portfolio.getNumStocks());
        Stock testStock = new Stock("AAPL", "Apple Inc");
        this.portfolio.removeStock(testStock);
        Assert.assertEquals(expectedSize - 1, portfolio.getNumStocks());
    }

    @Test
    public void testRemoveStock_DoesNotContainStock() {
        int expectedSize = 2;
        Assert.assertEquals(expectedSize, portfolio.getNumStocks());
        Stock testStock = new Stock("UTXL", "United Technologies Corporation");
        this.portfolio.removeStock(testStock);
        Assert.assertEquals(expectedSize, portfolio.getNumStocks());
    }

    @Test
    public void testGetNumShares_ContainsSymbol() {
        Map<String, Integer> expected = new HashMap<String, Integer>() {{
            put("AAPL", 100);
            put("ORCL", 1000);
        }};
        for (String symbol : expected.keySet()) {
            Assert.assertTrue(expected.get(symbol) == portfolio.getNumShares(symbol));
        }
    }

    @Test
    public void testGetNumShares_DoesNotContainSymbol() {
        Assert.assertEquals(0, portfolio.getNumShares("UTX"));
    }

    @Test
    public void testCalculateValue_BeforeFirstDate() throws ParseException {
        Date testDate = DATE_FORMAT.parse("2014-Jun-02");
        double expected = 89.807*100 + 41.97*1000;
        double actual = portfolio.calculateValue(testDate);
        Assert.assertEquals(expected, actual, TOLERANCE);
    }

    @Test
    public void testCalculateValue_AfterLastDate() throws ParseException {
        Date testDate = DATE_FORMAT.parse("2014-Jul-04");
        double expected = 92.117*100 + 41.70*1000;
        double actual = portfolio.calculateValue(testDate);
        Assert.assertEquals(expected, actual, TOLERANCE);
    }


    @Test
    public void testCalculateValue_Interpolate() throws ParseException {
        Date testDate = DATE_FORMAT.parse("2014-Jun-03");
        double expected = 90.962*100 + 41.835*1000;
        double actual = portfolio.calculateValue(testDate);
        Assert.assertEquals(expected, actual, TOLERANCE);
    }

    @Test
    public void testUpdateShares() {
        Stock testStock = new Stock("ORCL", "Oracle Corporation");
        Assert.assertEquals(1000, this.portfolio.getNumShares("ORCL"));

        this.portfolio.updateShares(testStock, 10);
        Assert.assertEquals(10, this.portfolio.getNumShares("ORCL"));
    }
}

答案 1 :(得分:0)

我认为你需要初始化你的清单。尝试:

List<Double> yl = new ArrayList<Double>();

目前,它为空,可能会给您带来问题。

答案 2 :(得分:0)

把这个

List<Double> yl = null;

之前的

for (Stock s : pfTable.getItems()) {

环。