/**
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.examples.report;
import static com.opengamma.strata.collect.Guavate.toImmutableList;
import static com.opengamma.strata.measure.StandardComponents.marketDataFactory;
import java.io.File;
import java.time.LocalDate;
import java.util.List;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.google.common.base.Strings;
import com.opengamma.strata.basics.ReferenceData;
import com.opengamma.strata.calc.CalculationRules;
import com.opengamma.strata.calc.CalculationRunner;
import com.opengamma.strata.calc.Column;
import com.opengamma.strata.calc.Results;
import com.opengamma.strata.calc.marketdata.MarketDataConfig;
import com.opengamma.strata.calc.marketdata.MarketDataRequirements;
import com.opengamma.strata.calc.runner.CalculationFunctions;
import com.opengamma.strata.calc.runner.CalculationTasks;
import com.opengamma.strata.collect.ArgChecker;
import com.opengamma.strata.collect.Messages;
import com.opengamma.strata.data.MarketData;
import com.opengamma.strata.examples.marketdata.ExampleMarketData;
import com.opengamma.strata.examples.marketdata.ExampleMarketDataBuilder;
import com.opengamma.strata.measure.StandardComponents;
import com.opengamma.strata.measure.rate.RatesMarketDataLookup;
import com.opengamma.strata.product.Trade;
import com.opengamma.strata.report.Report;
import com.opengamma.strata.report.ReportCalculationResults;
import com.opengamma.strata.report.ReportRequirements;
import com.opengamma.strata.report.ReportRunner;
import com.opengamma.strata.report.ReportTemplate;
import com.opengamma.strata.report.cashflow.CashFlowReportRunner;
import com.opengamma.strata.report.cashflow.CashFlowReportTemplate;
import com.opengamma.strata.report.framework.format.ReportOutputFormat;
import com.opengamma.strata.report.trade.TradeReportRunner;
import com.opengamma.strata.report.trade.TradeReportTemplate;
/**
* Tool for running a report from the command line.
*/
public final class ReportRunnerTool implements AutoCloseable {
/**
* The calculation runner.
*/
private final CalculationRunner runner;
@Parameter(
names = {"-t", "--template"},
description = "Report template input file",
required = true,
converter = ReportTemplateParameterConverter.class)
private ReportTemplate template;
@Parameter(
names = {"-m", "--marketdata"},
description = "Market data root directory",
validateValueWith = MarketDataRootValidator.class)
private File marketDataRoot;
@Parameter(
names = {"-p", "--portfolio"},
description = "Portfolio input file",
required = true,
converter = TradeListParameterConverter.class)
private TradeList tradeList;
@Parameter(
names = {"-d", "--date"},
description = "Valuation date, YYYY-MM-DD",
required = true,
converter = LocalDateParameterConverter.class)
private LocalDate valuationDate;
@Parameter(
names = {"-f", "--format"},
description = "Report output format, ascii or csv",
converter = ReportOutputFormatParameterConverter.class)
private ReportOutputFormat format = ReportOutputFormat.ASCII_TABLE;
@Parameter(
names = {"-i", "--id"},
description = "An ID by which to select a single trade")
private String idSearch;
@Parameter(
names = {"-h", "--help"},
description = "Displays this message",
help = true)
private boolean help;
@Parameter(
names = {"-v", "--version"},
description = "Prints the version of this tool",
help = true)
private boolean version;
/**
* Runs the tool.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
try (ReportRunnerTool reportRunner = new ReportRunnerTool(CalculationRunner.ofMultiThreaded())) {
JCommander commander = new JCommander(reportRunner);
commander.setProgramName(ReportRunnerTool.class.getSimpleName());
try {
commander.parse(args);
} catch (ParameterException e) {
System.err.println("Error: " + e.getMessage());
System.err.println();
commander.usage();
return;
}
if (reportRunner.help) {
commander.usage();
} else if (reportRunner.version) {
String versionName = ReportRunnerTool.class.getPackage().getImplementationVersion();
if (versionName == null) {
versionName = "unknown";
}
System.out.println("Strata Report Runner Tool, version " + versionName);
} else {
try {
reportRunner.run();
} catch (Exception e) {
System.err.println(Messages.format("Error: {}\n", e.getMessage()));
commander.usage();
}
}
}
}
//-------------------------------------------------------------------------
// creates an instance
private ReportRunnerTool(CalculationRunner runner) {
this.runner = ArgChecker.notNull(runner, "runner");
}
//-------------------------------------------------------------------------
private void run() {
ReportRunner<ReportTemplate> reportRunner = getReportRunner(template);
ReportRequirements requirements = reportRunner.requirements(template);
ReportCalculationResults calculationResults = runCalculationRequirements(requirements);
Report report = reportRunner.runReport(calculationResults, template);
switch (format) {
case ASCII_TABLE:
report.writeAsciiTable(System.out);
break;
case CSV:
report.writeCsv(System.out);
break;
}
}
private ReportCalculationResults runCalculationRequirements(ReportRequirements requirements) {
List<Column> columns = requirements.getTradeMeasureRequirements();
ExampleMarketDataBuilder marketDataBuilder =
marketDataRoot == null ? ExampleMarketData.builder() : ExampleMarketDataBuilder.ofPath(marketDataRoot.toPath());
CalculationFunctions functions = StandardComponents.calculationFunctions();
RatesMarketDataLookup ratesLookup = marketDataBuilder.ratesLookup(valuationDate);
CalculationRules rules = CalculationRules.of(functions, ratesLookup);
MarketData marketData = marketDataBuilder.buildSnapshot(valuationDate);
List<Trade> trades;
if (Strings.nullToEmpty(idSearch).trim().isEmpty()) {
trades = tradeList.getTrades();
} else {
trades = tradeList.getTrades().stream()
.filter(t -> t.getInfo().getId().isPresent())
.filter(t -> t.getInfo().getId().get().getValue().equals(idSearch))
.collect(toImmutableList());
if (trades.size() > 1) {
throw new IllegalArgumentException(
Messages.format("More than one trade found matching ID: '{}'", idSearch));
}
}
if (trades.isEmpty()) {
throw new IllegalArgumentException("No trades found. Please check the input portfolio or trade ID filter.");
}
// the reference data, such as holidays and securities
ReferenceData refData = ReferenceData.standard();
// calculate the results
CalculationTasks tasks = CalculationTasks.of(rules, trades, columns);
MarketDataRequirements reqs = tasks.requirements(refData);
MarketData calibratedMarketData = marketDataFactory().create(reqs, MarketDataConfig.empty(), marketData, refData);
Results results = runner.getTaskRunner().calculate(tasks, calibratedMarketData, refData);
return ReportCalculationResults.of(
valuationDate, trades, requirements.getTradeMeasureRequirements(), results, functions, refData);
}
@SuppressWarnings({"unchecked", "rawtypes"})
private ReportRunner<ReportTemplate> getReportRunner(ReportTemplate reportTemplate) {
// double-casts to achieve result type, allowing report runner to be used without external knowledge of template type
if (reportTemplate instanceof TradeReportTemplate) {
return (ReportRunner) TradeReportRunner.INSTANCE;
} else if (reportTemplate instanceof CashFlowReportTemplate) {
return (ReportRunner) CashFlowReportRunner.INSTANCE;
}
throw new IllegalArgumentException(Messages.format("Unsupported report type: {}", reportTemplate.getClass().getSimpleName()));
}
@Override
public void close() {
runner.close();
}
}