/*
* -------------------------------------------------------------------------
* $Id: Simulate.java,v 1.6 2004/05/26 19:03:12 estewart Exp $
* -------------------------------------------------------------------------
* Copyright (c) 1999 Visual Numerics Inc. All Rights Reserved.
*
* This software is confidential information which is proprietary to
* and a trade secret of Visual Numerics, Inc. Use, duplication or
* disclosure is subject to the terms of an appropriate license
* agreement.
*
* VISUAL NUMERICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
* SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. VISUAL
* NUMERICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
* ITS DERIVATIVES.
*--------------------------------------------------------------------------
*/
package com.imsl.demo.risk;
import com.imsl.chart.*;
import com.imsl.math.Cholesky;
import com.imsl.stat.*;
import com.imsl.IMSLException;
import java.text.*;
import java.awt.GridBagConstraints;
import javax.swing.*;
/**
*
* @author brophy
* @created January 31, 2002
*/
public class Simulate extends JFrameChart {
private Database db;
private AxisXY axis;
private Bar bar;
private Statistics statistics;
private int nSamples = 100000;
private double portfolioValues[] = {1000, 500, 1000, 0, 0};
private Cholesky chol;
private double bins[];
private Summary summary;
private EditPortfolio editPortfolio;
private MonteCarloProgress progress;
private boolean cancelMonteCarlo;
private PortfolioPie portfolioPie;
/** Creates new ChartReturns */
public Simulate(Database db, double covar[][]) throws IMSLException {
this.db = db;
setTitle("Risk Analysis");
Object l[] = getListeners(java.awt.event.WindowListener.class);
for (int k = 0; k < l.length; k++) {
removeWindowListener((java.awt.event.WindowListener)l[k]);
}
Chart chart = getChart();
chart.setTextColor("purple");
//chart.getBackground().setFillColor(new java.awt.Color(240,240,240));
axis = new AxisXY(chart);
axis.getAxisX().getAxisTitle().setTitle("Daily Returns");
axis.getAxisY().getAxisTitle().setTitle("Probability");
axis.getAxisX().getAxisLabel().setTextFormat(new java.text.DecimalFormat("0.0%"));
axis.getAxisY().getAxisLabel().setTextFormat(new java.text.DecimalFormat("0%"));
axis.getAxisX().getGrid().setPaint(true);
axis.getAxisY().getGrid().setPaint(true);
axis.getAxisX().getGrid().setLineColor("lightGray");
axis.getAxisY().getGrid().setLineColor("lightGray");
statistics = new Statistics();
statistics.setLocation(25,500);
statistics.show();
chol = new Cholesky(covar);
compute();
editPortfolio = new EditPortfolio(db.getTickers());
editPortfolio.setLocation(25,100);
//editPortfolio.show();
portfolioPie = new PortfolioPie(this);
portfolioPie.update(db.getTickers(), portfolioValues);
//com.imsl.math.PrintMatrixFormat pmf = new com.imsl.math.PrintMatrixFormat();
//pmf.setNumberFormat(new java.text.DecimalFormat("0.000E0"));
//new com.imsl.math.PrintMatrix().printHTML(pmf,covar,covar.length,covar.length);
}
public void setVisible(boolean vis) {
super.setVisible(vis);
if (vis) {
java.awt.Point chartLoc = getLocationOnScreen();
java.awt.Dimension statSize = statistics.getSize();
statistics.setLocation(chartLoc.x-statSize.width,chartLoc.y);
java.awt.Dimension portSize = editPortfolio.getSize();
editPortfolio.setLocation(chartLoc.x,chartLoc.y-portSize.height);
//java.awt.Dimension pieSize = portfolioPie.getSize();
//portfolioPie.setLocation(chartLoc.x-pieSize.width,chartLoc.y-pieSize.height);
portfolioPie.setSize(225,225);
portfolioPie.setLocation(chartLoc.x-225,chartLoc.y-225);
}
statistics.setVisible(vis);
editPortfolio.setVisible(vis);
portfolioPie.setVisible(vis);
}
public void cancelMonteCarlo() {
cancelMonteCarlo = true;
}
private void compute() {
cancelMonteCarlo = false;
progress = new MonteCarloProgress(this, 0, nSamples);
progress.setLocationRelativeTo(this);
progress.setVisible(true);
new Thread(new Runnable() {
public void run() {
runMonteCarlo();
}
}).start();
}
public void runMonteCarlo() {
int nVariables = portfolioValues.length;
int nBins = 50;
double max = 0.05;
summary = new Summary();
com.imsl.stat.Random random = new com.imsl.stat.Random();
double center = portfolio(new double[nVariables]);
// Setup the bins
bins = new double[nBins];
final double dx = 2.*max/nBins;
double x[] = new double[nBins];
for (int k = 0; k < nBins; k++) {
x[k] = -max + (k+0.5)*dx;
}
for (int p = 0; p < nSamples; p++) {
double r[] = random.nextMultivariateNormal(nVariables, chol);
double value = portfolio(r);
double t = (value-center)/center;
summary.update(t);
if (p%10000 == 0) progress.setValue(p);
if (cancelMonteCarlo) {
progress.setVisible(false);
return;
}
int j = (int)Math.round((t+max-0.5*dx)/dx);
if (j >= 0 && j < nBins) bins[j]++;
}
final double xx[] = x;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
updateChart(xx, dx);
}
});
}
private void updateChart(final double x[], double dx) {
progress.setVisible(false);
//getChart().getChartTitle().setTitle();
if (bar != null) bar.remove();
for (int k = 0; k < bins.length; k++) bins[k] /= nSamples;
bar = new Bar(axis, x, bins);
bar.setBarType(Bar.BAR_TYPE_VERTICAL);
bar.setFillColor("green");
bar.setBarWidth(0.5*dx);
axis.getAxisY().setWindow(0, 0.10);
axis.getAxisY().setAutoscaleInput(AxisXY.AUTOSCALE_OFF);
repaint();
StringBuffer sb = new StringBuffer(2048);
sb.append("<html><body>");
sb.append("<p align='center'><b>Returns</b></p>");
sb.append("<table>");
appendRow(sb, "Samples", nSamples);
appendRow(sb, "Minimum", summary.getMinimum());
appendRow(sb, "Maximum", summary.getMaximum());
appendRow(sb, "Mean", summary.getMean());
appendRow(sb, "Standard Deviation", summary.getStandardDeviation());
appendRow(sb, "Variance", summary.getVariance());
appendRow(sb, "Skewness", summary.getSkewness());
appendRow(sb, "Kurtosis", summary.getKurtosis());
sb.append("</table></body></html>");
statistics.setText(sb.toString());
statistics.repaint();
}
static final DecimalFormat formatStat = new DecimalFormat("0.00000E0");
private void appendRow(StringBuffer sb, String title, double value) {
sb.append("<tr><td align='right'><i>");
sb.append(title);
sb.append("</i></td><td align='left'>");
sb.append(formatStat.format(value));
sb.append("</td><tr>");
}
double portfolio(double returns[]) {
double sum = 0.0;
for (int k = 0; k < returns.length; k++) {
sum += portfolioValues[k] * (1.0+returns[k]);
}
return sum;
}
private class Statistics extends JDialog {
private JEditorPane jEditorPane;
public Statistics() {
super(Simulate.this, false);
setTitle("Summary Statistics");
jEditorPane = new JEditorPane();
jEditorPane.setContentType("text/html");
jEditorPane.setPreferredSize(new java.awt.Dimension(250,375));
getContentPane().add(jEditorPane);
pack();
}
void setText(String text) {
jEditorPane.setText(text);
}
}
private class EditPortfolio extends JDialog {
private JTextField jTextFieldSamples;
private JTextField jTextField[];
EditPortfolio(String tickers[]) {
setTitle("Edit");
getContentPane().setLayout(new java.awt.GridBagLayout());
GridBagConstraints gridBagConstraints = new GridBagConstraints();
JLabel jLabel = new JLabel("Samples");
jLabel.setHorizontalAlignment(SwingConstants.RIGHT);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
getContentPane().add(jLabel, gridBagConstraints);
jTextFieldSamples = new JTextField(Integer.toString(nSamples));
jTextFieldSamples.setHorizontalAlignment(JTextField.RIGHT);
jTextFieldSamples.setPreferredSize(new java.awt.Dimension(100,30));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
getContentPane().add(jTextFieldSamples, gridBagConstraints);
jTextField = new JTextField[tickers.length];
for (int k = 0; k < tickers.length; k++) {
jLabel = new JLabel(tickers[k]);
jLabel.setHorizontalAlignment(SwingConstants.RIGHT);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
getContentPane().add(jLabel, gridBagConstraints);
jTextField[k] = new JTextField(Double.toString(portfolioValues[k]));
jTextField[k].setHorizontalAlignment(JTextField.RIGHT);
jTextField[k].setPreferredSize(new java.awt.Dimension(100,30));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
getContentPane().add(jTextField[k], gridBagConstraints);
}
JButton jButton = new JButton("Update");
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
getContentPane().add(jButton, gridBagConstraints);
jButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
update();
}
});
pack();
}
private void update() {
nSamples = Integer.valueOf(jTextFieldSamples.getText()).intValue();
for (int k = 0; k < jTextField.length; k++) {
portfolioValues[k] = Double.valueOf(jTextField[k].getText()).doubleValue();
}
portfolioPie.update(db.getTickers(), portfolioValues);
Simulate.this.compute();
Simulate.this.repaint();
}
}
}