

public class SVPriceEngine {
  double npers, tinc, r1per, sigma0, meansigma, sigmasigma, kappa,
    c0, c1, c2, c3, c4;
  double stockP, sigma;

  public SVPriceEngine(){}

  public void newPars(double ttm,int nper,double r,double initstd,
    double meanstd, double k, double sigstd) {
    npers = nper;
    tinc = ttm/(double) nper;
    r1per = 1.0 + r*tinc;
    sigma0 = initstd;
    meansigma = meanstd;
    sigmasigma = sigstd;
    kappa = k;
    c0 = kappa * tinc * meansigma;
    c1 = 1.0 - kappa * tinc;
    c2 = 1.0 - sigmasigma * Math.sqrt(tinc)*0.5*Math.sqrt((double) 12);
    c3 = sigmasigma * Math.sqrt(tinc) * Math.sqrt((double) 12);
    c4 = Math.sqrt(tinc)*Math.sqrt((double) 12);}

public double eurCall(double stock,double strike,long nsimu) {
  long i,n;
  double x;
  x=0.0;
  for(n=0;n<nsimu;n++) {
    stockP = stock;
    sigma = sigma0;
    for(i=0;i<npers;i++) {
      stockP *= stocktotret();
      }
    x += Math.max(stockP-strike,0);}
  return(x/((double) nsimu * Math.pow(r1per,(double) npers)));}

double stocktotret() {
  double stockret;
//
//  The following straightforward computations are algebraically
//  the same as the ones used below but are much slower because
//  many more calculations are performed in each pass through the
//  nested for loops in eurCall.
//
//  stockret = r1per + sigma * Math.sqrt(tinc) *
//    (Math.random()-0.5) * Math.sqrt((double) 12);
//  sigma = (kappa*tinc * meansigma + (1.0 - kappa * tinc) * sigma) *
//    (1 + sigmasigma * Math.sqrt(tinc) * 
//    (Math.random()-0.5) * Math.sqrt((double) 12));
//  return(stockret);}
//
  stockret = r1per + sigma * c4 * (Math.random() - 0.5);
  sigma = (c0 + c1 * sigma) * (c2 + c3 * Math.random());
  return(stockret);}}
