Java tutorial
/**************************************************** Statistics Online Computational Resource (SOCR) http://www.StatisticsResource.org All SOCR programs, materials, tools and resources are developed by and freely disseminated to the entire community. Users may revise, extend, redistribute, modify under the terms of the Lesser GNU General Public License as published by the Open Source Initiative http://opensource.org/licenses/. All efforts should be made to develop and distribute factually correct, useful, portable and extensible resource all available in all digital formats for free over the Internet. SOCR resources are distributed in the hope that they will be useful, but without any warranty; without any explicit, implicit or implied warranty for merchantability or fitness for a particular purpose. See the GNU Lesser General Public License for more details see http://opensource.org/licenses/lgpl-license.php. http://www.SOCR.ucla.edu http://wiki.stat.ucla.edu/socr It s Online, Therefore, It Exists! ****************************************************/ package edu.ucla.stat.SOCR.applications.demo; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Point; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.geom.Rectangle2D; import java.beans.PropertyChangeListener; import java.text.DecimalFormat; import java.util.Iterator; import java.util.LinkedList; import java.util.Observable; import java.util.Observer; import edu.ucla.stat.SOCR.util.ValueSlider; import edu.ucla.stat.SOCR.core.IExperiment; import edu.ucla.stat.SOCR.util.FloatTextField; import javax.swing.*; import edu.uah.math.devices.Parameter; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PiePlot; import org.jfree.data.general.PieDataset; import org.jgraph.JGraph; import org.jgraph.graph.CellView; import org.jgraph.graph.DefaultEdge; import org.jgraph.graph.DefaultGraphCell; import org.jgraph.graph.DefaultGraphModel; import org.jgraph.graph.GraphConstants; import org.jgraph.graph.GraphModel; import edu.ucla.stat.SOCR.applications.Application; /** * The Binomial Trading Application demonstrates the Price of a stock call with time: * * Inputs: * S0 = Price of the stock at time zero (now). * E = Exercise price (it is exercised at the end if price of stock at the end > E). * t = Time until expiration in years, e.g. if t = 73 days, then t = 0.2. * r = Interest rate per year. * sigma = Annual volatility. * n = Number of periods that we divide the time to expiration (here n = 2). * */ public class BinomialTradingApplication extends Application implements Observer, IExperiment, ActionListener { protected final int CHART_SIZE_X = 500; /** * @uml.property name="cHART_SIZE_Y" */ protected final int CHART_SIZE_Y = 400; protected final String GRAPH = "Binomial Option Pricing Model"; // protected final String GRAPH2 = "GRAPH2"; protected JPanel jgraphPanel; protected ChartPanel chartPanel2; protected JGraph jgraph; int nodeCount = 0; int edgeCount = 0; int cellCount = 0; int YSize = 40; int XSize = 100; private DecimalFormat formatter = new DecimalFormat("#0.0##"); DefaultGraphCell[] cells = new DefaultGraphCell[100]; protected JSplitPane upContainer; protected int tabbedPaneCount = 0; public JTabbedPane tabbedPanelContainer; JToolBar toolBar; JPanel leftPanel = new JPanel(); Box inPanel = Box.createVerticalBox(); Box inputPanel = Box.createVerticalBox(); protected JTextField inSo, inEP, inR, inSigma; //ValueSlider tDaysSlider; FloatTextField nSlider, tDaysSlider; /* public JPanel masterPanel; public JSplitPane vSplitPane; public JPanel controlPanel = new JPanel(new BorderLayout()); public JPanel graphPanel = new JPanel(new BorderLayout());*/ // Binomial Trading Application Variables double So = 30; //Price of the stock at time zero (now). double EP = 29; //Exercise price (it is exercised at the end if price of stock at the end > EP). int t_days = 73; //0<=t_days<=365; Time until expiration in days, e.g. t_days = 73 days, double t = ((double) (t_days)) / 365; //0<=t<=1; Time until expiration in years, e.g. if t_days = 73 days, then t = 0.2. double rate = 0.05; //Interest rate per year. double sigma = 0.3; //Annual volatility. int n = 3; //Number of periods that we divide the time to expiration (here n = 2). double rp = Math.pow(1 + rate, t / n) - 1; // rp = interest rate-per-period double up = Math.exp(sigma * Math.sqrt(t / n)); // proportion UP price double down = 1 / up; // proportion DOWN price double probUp = (1 + rp - down) / (up - down); // Probability of Going UP. Prob of going DOWN is respectively (1-p) double[][] Price; // Price of the Stock Price[k][l] is the price of the stock at level k (0<=k<=n) // and outcome l (0<=l<n+1) double[][] Diff; // Difference = Price of the Call Diff[k][l] is the Call-Price of the stock at // level k (1<=k<=n) and outcome l (0<=l<n+1) String choice; // Whether the option pricing is European or American, Call or Put JComboBox gChoices; /** * This is the main constructor of BinomialTradingApplication objects. */ public BinomialTradingApplication() { setName("BinormialTradingApplication"); initInputPanel(); init(); } /** * This method initializes the application. */ public void init() { tabbedPanelContainer = new JTabbedPane(); initJGraphPanel(); initGraphPanel2(); addTabbedPane(GRAPH, jgraphPanel); //addTabbedPane("GRAPH2", graphPanel2); tabbedPanelContainer.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { if (tabbedPanelContainer.getTitleAt(tabbedPanelContainer.getSelectedIndex()) == GRAPH) { jgraphPanel.removeAll(); //setChart(); } /*else if( tabbedPanelContainer.getTitleAt(tabbedPanelContainer.getSelectedIndex())==GRAPH2) { // //setInputPanel(); }*/ } }); /* The following components need to be set * 1. Control JPanel * 1.a Floating-point Text-Field for So = Price of the stock at time zero, So>=0. * 1.b Floating-Point Text-Field for EP = Exercise price (it is exercised at the end if price of stock at the end > EP), EP>=0. * 1.c Integer Slider for t = Time until expiration in years, 0<=t<=365. * 1.d Floating-Point Text-Field for r = Interest rate per year (0.000<=r). * 1.e Floating Point Text-Field for sigma = Annual volatility (0.000<=sigma). * 1.f Integer Slider for n = Number of periods that we divide the time to expiration (0<=n<=1000). * * 2. Graph JPanel * 2.a For now, make this Graph panel just include a JTextArea where we will print out results * for debugging the calculator. Later, we'll replace this by a (Node, Edge)-Graph object * */ /*masterPanel = new JPanel(); masterPanel.setSize(new Dimension (500,500)); controlPanel.add(new JTextArea("Control Panel")); graphPanel.add(new JTextArea("Graph Panel")); vSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(controlPanel), new JScrollPane(graphPanel)); vSplitPane.setOneTouchExpandable(true); vSplitPane.setDividerLocation(150); //add(vSplitPane); // What should this be - how/where can we attach this pane to the main Panel? masterPanel.add(vSplitPane); masterPanel.validate(); getDisplayPane().removeAll(); getDisplayPane().add(masterPanel, BorderLayout.CENTER);*/ upContainer = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(leftPanel), new JScrollPane(tabbedPanelContainer)); this.getMainPanel().removeAll(); this.getMainPanel().add(new JScrollPane(upContainer), BorderLayout.CENTER); this.getMainPanel().validate(); //initGraph(); updateAllNodes(); } public void addTabbedPane(String name, JComponent c) { tabbedPanelContainer.addTab(name, c); tabbedPaneCount++; } /* The following components need to be set * 1. Control JPanel * 1.a Floating-point Text-Field for So = Price of the stock at time zero, So>=0. * 1.b Floating-Point Text-Field for EP = Exercise price (it is exercised at the end if price of stock at the end > EP), EP>=0. * 1.c Integer Slider for t = Time until expiration in years, 0<=t<=365. * 1.d Floating-Point Text-Field for r = Interest rate per year (0.000<=r). * 1.e Floating Point Text-Field for sigma = Annual volatility (0.000<=sigma). * 1.f Integer Slider for n = Number of periods that we divide the time to expiration (0<=n<=1000). */ private void initInputPanel() { leftPanel = new JPanel(); //inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.PAGE_AXIS)); //inPanel.setLayout(new BoxLayout(inPanel, BoxLayout.PAGE_AXIS)); JPanel jp0 = new JPanel(); jp0.add(new JLabel("S0")); inSo = new JTextField(14); inSo.addActionListener(this); inSo.setText("30"); inSo.setActionCommand("S0"); jp0.add(inSo); inputPanel.add(jp0); JPanel jp1 = new JPanel(); jp1.add(new JLabel("E")); inEP = new JTextField(14); inEP.setText("29"); inEP.addActionListener(this); inEP.setActionCommand("EP"); jp1.add(inEP); inputPanel.add(jp1); //tDaysSlider = new ValueSlider("Days", 0, 365, t_days, true); tDaysSlider = new FloatTextField("Days to expiration", t_days, 0, 365, false); tDaysSlider.addObserver(this); inputPanel.add(tDaysSlider); JPanel jp3 = new JPanel(); jp3.add(new JLabel("Interest")); inR = new JTextField(14); inR.setText("0.05"); inR.addActionListener(this); inR.setActionCommand("Rate"); jp3.add(inR); inputPanel.add(jp3); JPanel jp4 = new JPanel(); jp4.add(new JLabel("Sigma")); inSigma = new JTextField(14); inSigma.addActionListener(this); inSigma.setText("0.3"); inSigma.setActionCommand("Sigma"); jp4.add(inSigma); inputPanel.add(jp4); nSlider = new FloatTextField("Number of steps", n, 0, 1000, false); nSlider.addObserver(this); inputPanel.add(nSlider); // European Option Pricing or American Option Pricing gChoices = new JComboBox(); gChoices.setToolTipText("Select Binomial Option Pricing Method"); gChoices.addItem("European Call"); gChoices.addItem("European Put"); gChoices.addItem("American Call"); gChoices.addItem("American Put"); gChoices.addActionListener(this); JPanel jp5 = new JPanel(); jp5.add(new JLabel("Select Binomial Option Pricing Method")); inputPanel.add(jp5); JPanel jp6 = new JPanel(); jp6.add(gChoices); inputPanel.add(jp6); choice = "European Call"; inputPanel.add(inPanel); leftPanel.add(inputPanel, BorderLayout.NORTH); String text = " European Option: No early exercise allowed \n American Option: Early exercise allowed \n S: Stock Price \n C: Call Price \n P: Put Price \n\n At each node:\n First value = stock price\n Second value = call price"; getRecordTable().setText(text); } void initJGraphPanel() { jgraphPanel = new JPanel(); jgraphPanel.setLayout(new BoxLayout(jgraphPanel, BoxLayout.Y_AXIS)); // This method defines the Graph structure as an empty Graph object GraphModel model = new DefaultGraphModel(); jgraph = new JGraph(model); jgraphPanel.add(jgraph); jgraphPanel.validate(); } void initGraphPanel2() { // graphPanel2 = new JPanel(); // graphPanel2.setLayout(new BoxLayout(graphPanel2, BoxLayout.Y_AXIS)); // This method defines the Graph structure as an empty Graph object JFreeChart chart = createEmptyChart(null); //create a empty graph first chartPanel2 = new ChartPanel(chart, false); chartPanel2.setPreferredSize(new Dimension(CHART_SIZE_X, CHART_SIZE_Y)); // graphPanel2.add(chartPanel2); // graphPanel2.validate(); } protected JFreeChart createEmptyChart(PieDataset dataset) { JFreeChart chart = ChartFactory.createPieChart("SOCR Chart", // chart title null, // data true, // include legend true, false); PiePlot plot = (PiePlot) chart.getPlot(); plot.setLabelFont(new Font("SansSerif", Font.PLAIN, 12)); plot.setNoDataMessage("No data available"); plot.setCircular(false); plot.setLabelGap(0.02); return chart; } void updateGraph() { //This method will later update/redraw/repaint the (Node, Edge)-Graph // For now, we just print out the results in JTextArea // Price of the Stock Price[k][l] is the price of the stock at level k (0<=k<=n) // and outcome l (0<=l<n+1) GraphModel model = new DefaultGraphModel(); jgraph = new JGraph(model); cells = new DefaultGraphCell[((n + 1) * (n + 2) / 2) * 3]; cellCount = 0; int XSpace = 130; int YSpace = 30; int YMiddle = 20 + n * YSpace; //150 for (int k = 0; k <= n; k++) { //System.out.println("============Start-of-level("+k+")=================="); for (int l = 0; l <= k; l++) { // Print to GraphPanel's JTextArea int j = -k + l * 2; if (choice.charAt(9) == 'P') { //For put option if (k == n) { // For the last column, k=n, (in the money), // we need to color GREEN or BLUE the node-background // to indicate if the Call Price (C) is > 0 (green) or // <= 0 (blue) if (j < 0) { if (Diff[k][l] > 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " P[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace - 20), Color.green); else addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " P[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace - 20), Color.blue); } else if (j > 0) { if (Diff[k][l] > 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " P[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace + 20), Color.green); else addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " P[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace + 20), Color.blue); } else { if (Diff[k][l] > 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " P[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), YMiddle, Color.green); else addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " P[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), YMiddle, Color.blue); } } else { // For all columns before the last (in the money) column, k<n)! if (j < 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " P[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace - 20)); else if (j > 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " P[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace + 20)); else addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " P[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), YMiddle); } } else { //For call option if (k == n) { // For the last column, k=n, (in the money), // we need to color GREEN or BLUE the node-background // to indicate if the Call Price (C) is > 0 (green) or // <= 0 (blue) if (j < 0) { if (Diff[k][l] > 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace - 20), Color.green); else addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace - 20), Color.blue); } else if (j > 0) { if (Diff[k][l] > 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace + 20), Color.green); else addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace + 20), Color.blue); } else { if (Diff[k][l] > 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), YMiddle, Color.green); else addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), YMiddle, Color.blue); } } else if (choice.charAt(0) == 'A' && Diff[k][l] == Math.abs(Price[k][l] - EP)) { // For all columns before the last (in the money) column, k<n)! and possibly exercised early if (j < 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace - 20), Color.magenta); else if (j > 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace + 20), Color.magenta); else addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), YMiddle, Color.magenta); } else { // For all columns before the last (in the money) column, k<n)! if (j < 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace - 20)); else if (j > 0) addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), (YMiddle + j * YSpace + 20)); else addNode("S[" + k + "," + l + "]=" + formatter.format(Price[k][l]) + " C[" + k + "," + l + "]=" + formatter.format(Diff[k][l]), (10 + k * XSpace), YMiddle); // Also Print to STD_OUT // System.out.println("j="+j); // System.out.println("Price["+k+"]["+l+"]="+Price[k][l]); // System.out.println("Diff["+k+"]["+l+"]="+Diff[k][l]); } } } //System.out.println("============End-of-level("+k+")==================\n"); } //System.out.println("cellCount="+cellCount); for (int k = 0; k < n; k++) { //System.out.println("============Start-of-level("+k+")=================="); for (int l = 0; l <= k; l++) { // System.out.println((k*(k+1)/2+l)+"->"+((k+1)*(k+2)/2+l) ); addEdge((k * (k + 1) / 2 + l), ((k + 1) * (k + 2) / 2 + l)); //System.out.println((k*(k+1)/2+l)+"->"+((k+1)*(k+2)/2+l+1) ); addEdge((k * (k + 1) / 2 + l), ((k + 1) * (k + 2) / 2 + l + 1)); } // System.out.println("============End-of-level("+k+")==================\n"); } // System.out.println("cellCount="+cellCount); DefaultGraphCell[] cellsCache = new DefaultGraphCell[cellCount]; for (int i = 0; i < cellCount; i++) cellsCache[i] = cells[i]; jgraph.getGraphLayoutCache().insert(cellsCache); Dimension d = jgraph.getPreferredSize(); //System.out.println(d.width +","+d.height); jgraph.setPreferredSize(new Dimension(d.width + 150, d.height)); jgraphPanel.removeAll(); JScrollPane jsp = new JScrollPane(jgraph); jgraphPanel.add(jsp); jgraphPanel.setPreferredSize(new Dimension(CHART_SIZE_X, CHART_SIZE_Y)); JViewport jv = jsp.getViewport(); jv.setViewPosition(new Point(0, YMiddle - 150)); jgraphPanel.validate(); } public void actionPerformed(ActionEvent evt) { /* Here we need the action listeners for all of the user-specified parameters in the COntrol-Panel * See init() method!!! * 1.a Floating-point Text-Field for So = Price of the stock at time zero, So>=0. * 1.b Floating-Point Text-Field for EP = Exercise price (it is exercised at the end if price of stock at the end > EP), EP>=0. * 1.c Integer Slider for t = Time until expiration in years, 0<=t<=365. * 1.d Floating-Point Text-Field for r = Interest rate per year (0.000<=r). * 1.e Floating Point Text-Field for sigma = Annual volatility (0.000<=sigma). * 1.f Integer Slider for n = Number of periods that we divide the time to expiration (0<=n<=1000). */ //System.out.println(evt.getActionCommand()); if (evt.getSource() instanceof JComboBox) { JComboBox JCB = (JComboBox) evt.getSource(); choice = (String) JCB.getSelectedItem(); choice = choice.toLowerCase(); chartPanel2.validate(); inputPanel.validate(); } else if (evt.getActionCommand().equals("S0")) { So = Double.parseDouble(inSo.getText()); } else if (evt.getActionCommand().equals("EP")) { EP = Double.parseDouble(inEP.getText()); } else if (evt.getActionCommand().equals("Sigma")) { sigma = Double.parseDouble(inSigma.getText()); } else if (evt.getActionCommand().equals("Rate")) { rate = Double.parseDouble(inR.getText()); } updateAllNodes(); } public void update(Observable o, Object arg) { // TODO Auto-generated method stub if (n != nSlider.getFloatValue()) { n = (int) nSlider.getFloatValue(); //System.out.println("set n = " +n); } else if (t_days != tDaysSlider.getFloatValue()) { t_days = (int) tDaysSlider.getFloatValue(); //System.out.println("set t_days = " +t_days); } updateAllNodes(); return; } public void mouseClicked(MouseEvent event) { } public String getOnlineDescription() { return new String("http://www.socr.ucla.edu/"); } public Container getDisplayPane() { JSplitPane container = new JSplitPane(JSplitPane.VERTICAL_SPLIT, getMainPanel(), getTextPanel()); return container; } // Needs to be overwritten by objects that extend this class public String getAppletInfo() { return new String("SOCR Applications: http://www.socr.ucla.edu/htmls/app \n"); } public void update() { updateAllNodes(); } public void initialize() { // TODO Auto-generated method stub // DO we need this? } public DefaultGraphCell createVertex(String name, double x, double y, double w, double h, Color bg, boolean raised) { // Create vertex with the given name DefaultGraphCell cell = new DefaultGraphCell(name); /* ob.x = x; ob.y = y;*/ // System.out.println("adding node:"+ob.toString()+" to cell "+cellCount +"at ("+x+","+y+")"); // Set bounds GraphConstants.setBounds(cell.getAttributes(), new Rectangle2D.Double(x, y, w, h)); // Set fill color if (bg != null) { GraphConstants.setGradientColor(cell.getAttributes(), bg); GraphConstants.setOpaque(cell.getAttributes(), true); } // Set raised border if (raised) GraphConstants.setBorder(cell.getAttributes(), BorderFactory.createRaisedBevelBorder()); else // Set black border GraphConstants.setBorderColor(cell.getAttributes(), Color.black); // Add a Floating Port cell.addPort(); return cell; } public void addNode(String name, int x, int y) { //System.out.println("adding node:"+node.toString()+" to cell "+cellCount); cells[cellCount] = createVertex(name, x, y, XSize, YSize, Color.ORANGE, true); nodeCount++; cellCount++; } public void addNode(String name, int x, int y, Color backgroundColor) { //System.out.println("adding node:"+node.toString()+" to cell "+cellCount); cells[cellCount] = createVertex(name, x, y, XSize, YSize, backgroundColor, true); nodeCount++; cellCount++; } public void addEdge(int source, int target) { //System.out.println("adding edge: "+source+"->"+ target+ "to cell "+cellCount); DefaultEdge edge = new DefaultEdge(); edge.setSource(cells[source].getChildAt(0)); edge.setTarget(cells[target].getChildAt(0)); int arrow = GraphConstants.ARROW_CLASSIC; GraphConstants.setLineEnd(edge.getAttributes(), arrow); GraphConstants.setEndFill(edge.getAttributes(), true); // Node s = (Node)cells[source].getUserObject(); // Node t = (Node)cells[target].getUserObject(); /* _edge.arrow_x=(int)(s.x+t.x)/2; _edge.arrow_y=(int)(s.y+t.y)/2;*/ cells[cellCount] = edge; edgeCount++; cellCount++; } /* This method updates all the Nodes in the Binomial Trading Application * using the current values of the user-specified parameters (see top). */ public void updateAllNodes() { //System.out.println("so="+So+" E="+EP+" Days="+t_days+" interest="+rate+" Sigma="+sigma+" n="+n); if (0 <= t_days && t_days <= 365) t = ((double) (t_days)) / 365; else { System.out.println("Error -- The time (in days) must be in the range [0; 365]!"); t_days = 0; t = 0; } up = Math.exp(sigma * Math.sqrt(t / n)); // proportion UP price down = 1 / up; // proportion DOWN price Price = new double[n + 1][n + 1]; // Price of the Stock Price[k][l] is the price of the stock at // level k (0<=k<=n) and outcome l (0<=l<n+1) Diff = new double[n + 1][n + 1]; // Difference = Price of the Call Diff[k][l] is the Call-Price of the stock at // level k (1<=k<=n) and outcome l (0<=l<n+1) rp = Math.pow(1 + rate, t / n) - 1; // rp = interest rate-per-period //probUp= (1+rp-down)/(up-down); // Probability of Going UP. Prob of going DOWN is respectively (1-p) double dt = t / n; double a = Math.pow(Math.E, rate * dt); probUp = (a - down) / (up - down); // Compute the Stock Prices for (int k = 0; k <= n; k++) { //System.out.println("============Computing-StockPrices-at-level("+k+")=================="); for (int l = 0; l <= k; l++) { Price[k][l] = So * Math.pow(up, k - l) * Math.pow(down, l); // Print to GraphPanel's JTextArea // Also Print to STD_OUT //System.out.println("Price["+k+"]["+l+"]="+Price[k][l]); } //System.out.println("============End-of-level("+k+")==================\n"); } // Compute the DIFF values, Prices of calls for (int k = n; k >= 0; k--) { //System.out.println("============Computing DIFF (Price of call/put) at level("+k+")=================="); if (choice.indexOf("put") != -1) { //put if (k == n) { // These are the last leaf-nodes of the Binomial tree for (int l = 0; l <= k; l++) { if (Price[k][l] < EP) Diff[k][l] = EP - Price[k][l]; else Diff[k][l] = 0; // Price is NOT Excercised } } else { for (int l = 0; l <= k; l++) { // Print to GraphPanel's JTextArea //Diff[k][l] = (Diff[k+1][l]*probUp + Diff[k+1][l+1]*(1-probUp)) / (1+rp); --save Diff[k][l] = (Diff[k + 1][l] * probUp + Diff[k + 1][l + 1] * (1 - probUp)) * Math.pow(Math.E, -rate * dt); if (choice.indexOf("american") != -1 && (Diff[k][l] < EP - Price[k][l])) { Diff[k][l] = Price[k][l] - EP; } // Also Print to STD_OUT //System.out.println("Diff["+k+"]["+l+"] = "+Diff[k][l]); } //System.out.println("============End-of-level("+k+")==================\n"); } } else { //call if (k == n) { // These are the last leaf-nodes of the Binomial tree for (int l = 0; l <= k; l++) { if (Price[k][l] > EP) Diff[k][l] = Price[k][l] - EP; else Diff[k][l] = 0; // Price is NOT Excercised } } else { for (int l = 0; l <= k; l++) { // Print to GraphPanel's JTextArea //Diff[k][l] = (Diff[k+1][l]*probUp + Diff[k+1][l+1]*(1-probUp)) / (1+rp); --save Diff[k][l] = (Diff[k + 1][l] * probUp + Diff[k + 1][l + 1] * (1 - probUp)) * Math.pow(Math.E, -rate * dt); if (choice.indexOf("american") != -1 && (Diff[k][l] < Price[k][l] - EP)) { //int americanCall = (Price[k][l]*probUp + Price[k][l]*(1-probUp))*Math.pow(Math.E, -rate*dt); //if (americanCall > Diff[k][l]) // Diff[k][l] = americanCall; Diff[k][l] = Price[k][l] - EP; } // Also Print to STD_OUT //System.out.println("Diff["+k+"]["+l+"] = "+Diff[k][l]); } //System.out.println("============End-of-level("+k+")==================\n"); } } } updateGraph(); } }