jopt.java
import java.awt.*;
import java.applet.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class jopt extends Applet {
int xExtent, yExtent;
Option option;
dialogOption dialog;
public void init() {
option = new Option();
dialog = new dialogOption("Properties");
xExtent = 300;
yExtent = 300;
}
public void paint( Graphics g ) {
g.setColor(Color.white);
g.fillRect(0, 0, xExtent, yExtent);
option.paint(g);
}
public void updateOpt(float stock, float strike, float sd, float rate, float time, int type, int iv) {
option.update((double)stock, (double)strike, (double)sd, (double)rate, (double)time, type, iv);
repaint();
}
public boolean mouseDown(Event evt, int x, int y) {
option = dialog.show(option);
repaint();
return true;
}
}
class Option {
double stock, strike, sd, rate, time, price;
double startX, startY, scaleX, scaleY;
int type, iv;
Color color;
boolean manScale;
public Option() {
stock = 42;
strike = 40;
sd = .2;
rate = .10;
time = 0.5;
type = 1;
iv = 2;
price = price();
color = Color.red;
manScale = false;
}
public void update(double s, double x, double standev, double r, double t, int tp, int v) {
stock = s;
strike = x;
sd = standev;
rate = r;
time = t;
type = tp;
iv = v;
price = price();
}
public void paint( Graphics g ) {
int height = 190;
int width = 240;
int orgX = 30;
int orgY = 30;
String axisX = "";
Font font = g.getFont();
FontMetrics fontMetrics = g.getFontMetrics(font);
orgX = 15 + fontMetrics.stringWidth("8.88");
g.setColor(Color.black);
g.drawString("Price: " + round(price, 3), orgX,
orgY + height + 10 + fontMetrics.getAscent() * 3);
if ( ! manScale ) {
startY = 0;
scaleY = price * 3;
switch ( iv ) {
case 0:
scaleX = 16 * Math.abs(stock - strike);
startX = stock - (scaleX / 2);
axisX = "S";
break;
case 1:
scaleX = 4 * Math.abs(stock - strike);
startX = strike - scaleX / 2;
axisX = "X";
break;
case 2:
scaleX = 2 * sd;
startX = 0;
axisX = "s";
break;
case 3:
scaleX = 2 * rate;
startX = 0;
axisX = "r";
break;
case 4:
scaleX = 2 * time;
startX = 0;
axisX = "t";
break;
default:
startX = startY = scaleX = scaleY = 0;
break;
}
}
g.drawLine(orgX, orgY, orgX, orgY + height);
g.drawLine(orgX, orgY+ height, orgX + width, orgY + height);
g.drawString(axisX, orgX + width + fontMetrics.stringWidth("A"),
orgY + height + (fontMetrics.getAscent() / 2));
g.drawString("P", orgX - (fontMetrics.stringWidth("P") / 2),
orgY - (int)((double)fontMetrics.getAscent() / 2));
double nLabel;
String strLabel;
int n = 0;
for ( int i = orgX; i <= orgX + width; i += width/5 ) {
g.drawLine(i, orgY + height, i, orgY + height + 5);
nLabel = ( startX + ( ( scaleX / 5 ) * n++ ) );
if ( iv == 2 || iv == 3 ) {
nLabel *= 100;
}
strLabel = round( nLabel, 1);
g.drawString(strLabel, i - fontMetrics.stringWidth(strLabel) / 2,
orgY + height + 10 + fontMetrics.getAscent());
}
n = 0;
for ( int i = orgY + height; i >= orgY; i -= height/5 ) {
g.drawLine(orgX - 5, i, orgX, i);
nLabel = ( startY + ( ( scaleY / 5 ) * n++ ) );
strLabel = round( nLabel, 1);
g.drawString(strLabel, orgX - 10 - (fontMetrics.stringWidth(strLabel)),
i + (int)(fontMetrics.getAscent() / 2));
}
g.setColor(color);
double oldValue = 0;
boolean first = true;
int y, oldX, oldY;
y = oldY = oldX = 0;
for ( int x = orgX; x <= orgX + width; x++ ) {
switch ( iv ) {
case 0:
if ( first ) oldValue = stock;
stock = startX + (((double)( x - orgX ) / width) * scaleX);
break;
case 1:
if ( first ) oldValue = strike;
strike = startX + (((double)( x - orgX ) / width) * scaleX);
break;
case 2:
if ( first ) oldValue = sd;
sd = startX + (((double)( x - orgX ) / width) * scaleX);
break;
case 3:
if ( first ) oldValue = rate;
rate = startX + (((double)( x - orgX ) / width) * scaleX);
break;
case 4:
if ( first ) oldValue = time;
time = startX + (((double)( x - orgX ) / width) * scaleX);
break;
default:
oldValue = 0;
}
y = orgY + height - (int)((price() / scaleY) * height);
if ( first || y < orgY ) {
oldX = x;
oldY = y;
first = false;
}
else {
g.drawLine(oldX, oldY, x, y);
oldX = x;
oldY = y;
}
}
switch ( iv ) {
case 0:
stock = oldValue;
break;
case 1:
strike = oldValue;
break;
case 2:
sd = oldValue;
break;
case 3:
rate = oldValue;
break;
case 4:
time = oldValue;
break;
}
}
private String round( double n, int places ) {
int res = (int) ( n * Math.pow(10, places) + 0.5 );
String r = String.valueOf(res);
String result = r.substring(0, r.length() - places);
result += ".";
result += r.substring(r.length() - places, r.length());
if ( result.charAt(0) == '.' ) {
result = "0" + result;
}
return result;
}
private double price() {
double result;
if ( type == 1 ) {
result = stock * calcN( calcD(1) );
result -= strike * Math.exp( -rate * time ) * calcN( calcD(2) );
return result;
}
else if ( type == 2 ) {
result = strike * Math.exp( -rate * time ) * calcN( -(calcD(2)) );
result -= stock * calcN( -(calcD(1) ));
return result;
}
else {
return 0;
}
}
private double calcD( int D ) {
double result;
if ( D == 1 ) {
result = ( rate + ( Math.pow(sd, 2) / 2 ) ) * time;
}
else if ( D == 2 ) {
result = ( rate - ( Math.pow(sd, 2) / 2 ) ) * time;
}
else {
return 0;
}
result += Math.log( stock / strike );
result /= sd * Math.sqrt( time );
return result;
}
private double calcN( double n ) {
double result;
double x = Math.abs( n );
double l = 0.33267d;
double a1 = 0.4361836d;
double a2 = -0.1201676d;
double a3 = 0.9372980d;
double k = 1 / ( 1 + ( x * l ) );
double N = ( 1 / Math.sqrt( Math.PI * 2 ) );
N *= Math.exp( - (Math.pow(x, 2) / 2));
result = N * ((a1*k) + (a2*Math.pow(k,2)) + (a3*Math.pow(k,3)));
result = 1 - result;
if ( n >= 0 ) {
return result;
}
else {
return ( 1 - result );
}
}
public String getXL() {
if ( iv == 2 || iv == 3 ) {
return round(startX * 100, 1);
}
else {
return round(startX, 1);
}
}
public String getXR() {
if ( iv == 2 || iv == 3 ) {
return round((startX + scaleX) * 100, 1);
}
else {
return round(startX + scaleX, 1);
}
}
public String getYD() {
return round(startY, 1);
}
public String getYU() {
return round(startY + scaleY, 1);
}
public void setScale(double x1, double x2, double y1, double y2) {
manScale = true;
startX = x1;
scaleX = x2 - x1;
startY = y1;
scaleY = y2 - y1;
if ( iv ==2 || iv == 3 ) {
startX /= 100;
scaleX /= 100;
}
}
public void resetScale() {
manScale = false;
}
}
class dialogOption extends Frame implements ActionListener {
Dialog dialog;
TextField textField[];
Label label[];
Button OKButton;
Checkbox manScale;
boolean badInput;
Option option, oldOption;
dialogOption( String title ) {
dialog = new Dialog(this, title, true);
GridBagLayout layout = new GridBagLayout();
manScale = new Checkbox("Set scale manually?", null, true);
dialog.setLayout(layout);
badInput = false;
GridBagConstraints cons = new GridBagConstraints();
cons.fill = GridBagConstraints.BOTH;
textField = new TextField[4];
label = new Label[6];
textField[0] = new TextField("", 10);
textField[1] = new TextField("", 10);
textField[2] = new TextField("", 10);
textField[3] = new TextField("", 10);
label[0] = new Label("X left:", Label.LEFT);
label[1] = new Label("X right:", Label.LEFT);
label[2] = new Label("Y bottom:", Label.LEFT);
label[3] = new Label("Y up:", Label.LEFT);
label[4] = new Label("", Label.LEFT);
label[5] = new Label("", Label.LEFT);
OKButton = new Button("OK");
OKButton.addActionListener(this);
cons.gridwidth = GridBagConstraints.REMAINDER;
layout.setConstraints(manScale,cons);
dialog.add(manScale);
cons.gridwidth = GridBagConstraints.REMAINDER;
layout.setConstraints(label[4],cons);
dialog.add(label[4]);
for ( int i = 0; i < 4; i++ ) {
cons.gridwidth = GridBagConstraints.RELATIVE;
layout.setConstraints(label[i],cons);
dialog.add(label[i]);
cons.gridwidth = GridBagConstraints.REMAINDER;
layout.setConstraints(textField[i],cons);
dialog.add(textField[i]);
}
cons.gridwidth = GridBagConstraints.REMAINDER;
layout.setConstraints(label[5],cons);
dialog.add(label[5]);
cons.gridwidth = GridBagConstraints.REMAINDER;
layout.setConstraints(OKButton,cons);
dialog.add(OKButton);
}
public Option show( Option opt ) {
option = opt;
oldOption = option;
textField[0].setText(option.getXL());
textField[1].setText(option.getXR());
textField[2].setText(option.getYD());
textField[3].setText(option.getYU());
dialog.setSize(300, 300);
dialog.setVisible(true);
if ( badInput ) {
return oldOption;
}
else {
return option;
}
}
public void hide() {
dialog.setVisible(false);
}
public void actionPerformed(ActionEvent e){
Option tempOption = option;
double results[];
results = new double[4];
for ( int i = 0; i < 4; i++ ) {
try {
results[i] = Double.valueOf(textField[i].getText()).doubleValue();
}
catch (NumberFormatException ex) {
badInput = true;
}
}
if ( manScale.getState() && ! badInput ) {
option.setScale(results[0], results[1], results[2], results[3]);
}
else {
option.resetScale();
}
hide();
}
}
Please send all comments, suggestions, bug reports etc to mail@paulgriffiths.net