// Copyright 2015 Ivan Popivanov
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package net.tradelib.core;
import static org.junit.Assert.*;
import java.io.FileReader;
import java.math.BigDecimal;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import net.tradelib.core.Instrument;
import net.tradelib.core.Portfolio;
import net.tradelib.core.TimeSeries;
import org.junit.Test;
import com.google.common.collect.TreeBasedTable;
import com.opencsv.CSVReader;
public class PortfolioTest {
private TimeSeries<Double> fromCsv(String path, boolean hasHeader) throws Exception {
CSVReader csv = new CSVReader(new FileReader(path));
String [] line = csv.readNext();
if(line == null) return null;
TimeSeries<Double> ts = new TimeSeries<Double>(line.length - 1);
if(hasHeader) {
line = csv.readNext();
if(line == null) return null;
}
Double [] values = new Double[line.length - 1];
for(; line != null; line = csv.readNext()) {
for(int ii = 0; ii < values.length; ++ii) {
values[ii] = Double.parseDouble(line[ii + 1]);
}
ts.add(LocalDate.parse(line[0], DateTimeFormatter.ofPattern("yyyyMMdd")).atTime(17, 0), values);
}
ts.setNames("open","high","low","close","volume","interest");
return ts;
}
@Test
public void testBasic() throws Exception {
Instrument esInstrument = Instrument.makeFuture("ES", new BigDecimal("0.25"), new BigDecimal("50"));
Portfolio portfolio = new Portfolio();
portfolio.addInstrument(esInstrument);
TimeSeries<Double> es = fromCsv(
Paths.get(getClass().getResource("/data/es.csv").toURI()).toString(),
false);
double contractFees = -1.13;
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 1, 2, 17, 0, 0), 1, 1819.50, contractFees*1.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 1, 9, 17, 0, 0), 2, 1826, contractFees*2.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 1, 16, 17, 0, 0), -3, 1829.25, contractFees*3.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 1, 24, 17, 0, 0), -2, 1775.00, contractFees*2.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 1, 31, 17, 0, 0), 3, 1769.50, contractFees*3.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 2, 7, 17, 0, 0), -2, 1786.50, contractFees*2.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 2, 14, 17, 0, 0), 1, 1828.00, contractFees*1.0);
TimeSeries<Double> pnl = portfolio.getPnlOld(esInstrument, es.subset("2013-12-31", "2014-02-18").columns("close"));
// for(int ii = 0; ii < pnl.size(); ++ii) {
// System.out.println(pnl.getTimestamp(ii).format(DateTimeFormatter.ISO_DATE_TIME) + " " + String.valueOf(pnl.get(ii)));
// }
assertEquals(pnl.get("2014-01-02T17:00:00"), contractFees, 1e-8);
assertEquals(pnl.get("2014-01-03T17:00:00"), -50.0, 1e-8);
assertEquals(pnl.get("2014-01-06T17:00:00"), -237.5, 1e-8);
assertEquals(pnl.get("2014-01-07T17:00:00"), 500.0, 1e-8);
assertEquals(pnl.get("2014-01-08T17:00:00"), 87.5, 1e-8);
assertEquals(pnl.get("2014-01-09T17:00:00"), 22.74, 1e-8);
assertEquals(pnl.get("2014-01-10T17:00:00"), 712.5, 1e-8);
assertEquals(pnl.get("2014-01-13T17:00:00"), -3412.5, 1e-8);
assertEquals(pnl.get("2014-01-14T17:00:00"), 2700.0, 1e-8);
assertEquals(pnl.get("2014-01-15T17:00:00"), 1275.0, 1e-8);
assertEquals(pnl.get("2014-01-16T17:00:00"), -790.89, 1e-8);
assertEquals(pnl.get("2014-01-17T17:00:00"), 0.0, 1e-8);
assertEquals(pnl.get("2014-01-23T17:00:00"), 0.0, 1e-8);
assertEquals(pnl.get("2014-01-24T17:00:00"), -2.26, 1e-8);
assertEquals(pnl.get("2014-01-27T17:00:00"), 625.0, 1e-8);
assertEquals(pnl.get("2014-01-28T17:00:00"), -1250, 1e-8);
assertEquals(pnl.get("2014-01-29T17:00:00"), 1700.0, 1e-8);
assertEquals(pnl.get("2014-01-30T17:00:00"), -1000.0, 1e-8);
assertEquals(pnl.get("2014-01-31T17:00:00"), 472.74, 1e-8);
assertEquals(pnl.get("2014-02-03T17:00:00"), -2187.5, 1e-8);
assertEquals(pnl.get("2014-02-04T17:00:00"), 550.0, 1e-8);
assertEquals(pnl.get("2014-02-05T17:00:00"), 12.5, 1e-8);
assertEquals(pnl.get("2014-02-06T17:00:00"), 1125.0, 1e-8);
assertEquals(pnl.get("2014-02-07T17:00:00"), 1348.87, 1e-8);
assertEquals(pnl.get("2014-02-10T17:00:00"), -62.5, 1e-8);
assertEquals(pnl.get("2014-02-11T17:00:00"), -937.5, 1e-8);
assertEquals(pnl.get("2014-02-12T17:00:00"), -175.0, 1e-8);
assertEquals(pnl.get("2014-02-13T17:00:00"), -362.5, 1e-8);
assertEquals(pnl.get("2014-02-14T17:00:00"), -538.63, 1e-8);
assertEquals(pnl.get("2014-02-18T17:00:00"), 0.0, 1e-8);
}
@Test
public void testUpdatePositionPnl() throws Exception {
Instrument esInstrument = Instrument.makeFuture("ES", new BigDecimal("0.25"), new BigDecimal("50"));
Portfolio portfolio = new Portfolio();
portfolio.addInstrument(esInstrument);
TimeSeries<Double> es = fromCsv(
Paths.get(getClass().getResource("/data/es.csv").toURI()).toString(),
false);
double contractFees = -1.13;
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 1, 2, 17, 0, 0), 1, 1819.50, contractFees*1.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 1, 9, 17, 0, 0), 2, 1826, contractFees*2.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 1, 16, 17, 0, 0), -3, 1829.25, contractFees*3.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 1, 24, 17, 0, 0), -2, 1775.00, contractFees*2.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 1, 31, 17, 0, 0), 3, 1769.50, contractFees*3.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 2, 7, 17, 0, 0), -2, 1786.50, contractFees*2.0);
portfolio.addTransaction(esInstrument, LocalDateTime.of(2014, 2, 14, 17, 0, 0), 1, 1828.00, contractFees*1.0);
portfolio.updatePnl(esInstrument, es.subset("2013-12-31", "2014-02-18").columns("close"));
}
}