在我的投资组合应用程序中,我有一个包含股票头衔和投资组合权重的表对于每个股票标题,我正在下载特定时间窗口的价格。现在我正在尝试计算平均投资组合利率。
每日公式:
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;
}
}
感谢。
答案 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()) {
环。