#include <iostream.h>
#include <string>
#include <sstream>
#include <fstream>
#include <stdio.h>
#include <math.h>

#define DEBUG 0

double *a;
double *b;
double *c;
double *p;
double *q;
//this sets global variables that will be used in the main and other functions
class Node
{
//initializes all the functions that can be called by nodes
public:
  Node();
  Node(int t_num_lefts, int t_num_rights, int t_depth, double values);
  void AddLeftNode(int t_value);
  void AddRightNode(int t_value);
  void BuildTree(int t_depth);
  double GetValue();
  void PrintNode();
  double ValueTree();
  void ZTree();
  void NTree();
  double ValueLet(int let, double let_val, char typ1, char typ3);
  double ValueFull(int full, double full_val, char typ1, char typ3);
private:
  double value;
  double value2;
  int num_lefts;
  int num_rights;
  int depth;
  int depth_tree;
  double zvalue;
  double pvalue;
  Node *node_parent;
  Node *node_left;
  Node *node_right;
  void ValueFunction();
};

Node::Node()
{
//variables held by Node 0, the root.
  num_lefts=0;
//number of down movements
  num_rights=0;
//number of up movements
  depth=0;
//depth of the node
  depth_tree=0;
  ValueFunction();
//calls the models value function to assign the discount rate from interest rates for this node
  c[depth]= value;
//adds its discount rate to a running counter for all nodes of the same depth. will be used to find the zero coupon bond price
  value2 = value;
//will be used to give the discount function
}

Node::Node(int t_num_lefts, int t_num_rights, int t_depth, double values)
{
//counters increment lefts and rights, if needed. Like the root node, but now values are passed into this node from its parent and changed accordingly.
  num_lefts = t_num_lefts;
  num_rights = t_num_rights;
  depth = t_depth;
  ValueFunction();
  value2 = value * values;
//q is the risk neutral probability of evolution shift. Set at .5.
  c[depth]= c[depth] + (value2)*(pow(p[0],num_rights))*(pow(q[0],num_lefts));
  if(DEBUG)
    {
//gives the debug option to see all values entered into a node
      PrintNode();
    }
}

void Node::BuildTree(int t_depth_tree)
{
//this function recursively builds the tree
  depth_tree = t_depth_tree;

  if(depth_tree > 1)
    {
//depth_tree is the number of steps left in building a tree. if more than one steps is left, the function gets called again.
      AddLeftNode(1);
      AddRightNode(1);
    }
}

void Node::AddLeftNode(int t_value)
{
//adds the left node. equivalent to a downward step.
  node_left = new Node();
  *node_left = Node(num_lefts+1, num_rights, depth+1, value2);

  node_left->BuildTree(depth_tree-1);
}

void Node::AddRightNode(int t_value)
{
//adds the right node, equivalent to an up step.
  node_right = new Node();
  *node_right = Node(num_lefts, num_rights+1, depth+1, value2);

  node_right->BuildTree(depth_tree-1);
}

double Node::GetValue()
{
//function that returns the value of the discount rate
  return value;
}

void Node::PrintNode()
{
//function that prints the node values
  cout << "Created Node( " << depth << ", " << num_lefts << ", " << num_rights << ", " << value<< ")" << endl;
}

void Node::ValueFunction()
{
//values a node's discount rate by finding the interest rates given by a model. The Ho-Lee implementation uses continuous rates transformed into discrete rates as described in the paper, section 4
  //  value = 1/(1+a[depth] + (num_rights * b[depth]));
  value = 1/(exp(a[depth] + (num_rights * b[depth])));
  //  cout<<1/value<<endl;
}

void Node::ZTree()
{
//recursively assigns the forward measure values, Z and P. c[depth] was the zero coupon bond price, and 1/(pow(2,depth)) gives the risk neutral probability
  zvalue = value2 / c[depth];
  pvalue = zvalue * 1/(pow(2,depth));
  //  cout<< depth << " " << pvalue << " " << zvalue << " " << c[depth] << " " << value2 << " " <<  endl;

  if(depth_tree > 1)
    {
      node_left->ZTree();
      node_right->ZTree();
    }
}
void Node::NTree()
{
//like the Ztree function, but assigns risk neutral probabilities.
  pvalue = 1/(pow(2,depth));

  if(depth_tree > 1)
    {
      node_left->NTree();
      node_right->NTree();
    }

}


double Node::ValueLet(int let, double let_val, char typ1, char typ3)
{
//function for pricing caplet or floorlet functions
  double r_value = 0;
//w and e are sign +/- variables to create floor or cap pricing
  double w;
  double e;
  double vals;
  double rate = 1/value - 1;
//finds wether pricing should be under forward or risk neutral measures
  if (typ3 == 'F')
  {
	vals = c[depth];
  }
  else
  {
  	vals = value2;
  }
  if (depth < let-1)
  {
//searches for the proper depth to price the -let
   r_value = node_left->ValueLet(let, let_val, typ1, typ3) + node_right->ValueLet(let, let_val, typ1, typ3);
  }
  else {
    if (depth == let - 1)
      {
	if (typ1 == 'C')
	  {
	    w = 1.0; 
	    e = -1.0;
	  }
	else
	  {
	    w = -1.0; 
	    e = 1.0;
	  }
	if  ((w * rate) + (e * let_val) > 0)
	  {
//	    	    cout<< rate<< " " << let_val << " " << value2 << " " << pvalue << endl;
//prices the -let and stops recursion
	    r_value = ((w * rate) + (e * let_val)) * vals * pvalue;
	  }
      }
    }
  return r_value;
}


double Node::ValueFull(int full, double full_val, char typ1, char typ3)
{
//like the let functions, but this is a full Cap or Floor. Meaning that it does the -let calculations for every depth until it reaches the proper one, instead of just once.
  double r_value = 0;
  double w;
  double vals;
  double e;
  double rate = 1/value -1;
  if (typ3 == 'F')
  {
	vals = c[depth];
  }
  else
  {
  	vals = value2;
  }
  if (typ1 == 'C')
    {
      w = 1.0;
      e = -1.0;
    }
  else
    {
      w = -1.0;
      e = 1.0;
    }
  if (depth < full-1)
    {
      
      if  ((w * rate) + (e * full_val) > 0)
	{
	  //cout<< rate<< " " << full_val << " " << value2 << " " << pvalue << endl;
	  r_value = (((w * rate) + (e * full_val)) * vals * pvalue) + node_left->ValueFull(full, full_val, typ1, typ3) + node_right->ValueFull(full, full_val, typ1, typ3);
	}
      else
	{
	  r_value = node_left->ValueFull(full, full_val, typ1, typ3) + node_right->ValueFull(full, full_val, typ1, typ3);
	}
    }
    
  else
    {
      if (depth == full - 1)
	{
	  if  ((w * rate) + (e * full_val) > 0)
	    {
//	      cout<< rate<< " " << full_val << " " << value2 << " " << pvalue << endl;
	      r_value = ((w * rate) + (e * full_val)) * vals * pvalue;
	    }
	}
    }
  return r_value;
}





double Node::ValueTree()
{
//function goes through and finds all the discount functions, if necessary. Not used in current implementation.
  double r_value = 0;
  if(depth_tree<=1)
    {
      r_value=value;
    }
  else
    {
      r_value =.5*(value * node_left->ValueTree()) + .5*(value * node_right->ValueTree());
    }
  return r_value;
}

int StrToInt(const std::string &str)
{
//function to change strings to integers
  std::istringstream is (str);
  int i;
  is >> i;

  return i;
}

double StrToDouble(const std::string &str)
{
//function to change strings to doubles
  std::istringstream is (str);
  double i;
  is >> i;
  return i;

}
int main()
{
//main function, reads in a csv file and works the pricing for each line
  std::string A;
  std::ifstream inFile("voldata4.csv");
  double n=0;
  char *buf;
  char *temp;
  int size=0;
// probability variables
  q=(double*)malloc(int(1)*sizeof(double));
  p=(double*)malloc(int(1)*sizeof(double));
  q[0]=.5;
  p[0]= 1- q[0];
    
//checks to make sure file exists and is readable
 
  if (inFile.fail()) 
    {
      cerr << "unable to open file input.dat for reading" << endl;
      exit(1);
    }
  int d = 0;
//starts a while loop to get each line.
  while(std::getline(inFile,A))
    {
//counter of each line
      d++;
      cout<< d << ":" << endl;
//temporary comma deliminated variable, assigned to various permanent variable.
      char *tok;
//counter of variables read in each line
      int counter=0;
      buf=(char*)malloc(A.length()*sizeof(char));

      A.copy(buf,std::string::npos);

      tok = strtok(buf,",");
//splits line by commas, and goes through each one assigning it to tok
      while(tok != NULL)
	{
	  if(counter==0)
	    {
//finds the N value of the tree, and allocates space for a b and c arrays. a and b are the ho-lee variables. c is the zero coupon bond price
	      n=StrToDouble(tok);
	      a=(double*)malloc(int(n)*sizeof(double));
	      b=(double*)malloc(int(n)*sizeof(double));
	      c=(double*)malloc(int(n)*sizeof(double));
	    }
	  else if(counter>=1 && counter <=int(n))
	    {
//the next n variables are assigned to be a's
	      a[counter-1]=StrToDouble(tok);
	      if(DEBUG)
		{
		  cout << "a[" << counter-1 << "]=" << a[counter-1] << endl; 
		}
	    }
	  else
	    {
//the last n variables are assigned to be b's
	      b[counter-1-int(n)]=StrToDouble(tok);
	      if(DEBUG)
		{
		  cout << "b[" << counter-1-int(n) << "]=" << b[counter-1-int(n)] << endl; 
		}
	    }
	  tok = strtok(NULL,",");
	  counter++;
	}
//initializes the c's to be 0
      for (int i =0; i < n; i++) {c[i]=0;}
//calls a new root
      Node *root = new Node();
      //builds a tree of size n, as found from the file. includes finding the zero-coupon bond prices
      root->BuildTree(int(n));
      // cout << root->ValueTree() << endl;
//displays the read in variables
      cout << "With AB[n,n] := [";
      for (int i = 0; i < n; i++)
	{ 
	  cout << "(" << a[i] << "," << b[i] << ")";
	  if (i != n - 1)
	    { 
	      cout << ",";
	    }
	}
      cout << "]" <<endl;
      for (int i = 0; i < n; i++)
//displays the c's, which are zero-coupon bond prices
      {cout << "B0," <<i+1 << ": " << c[i] << endl;} 
      //      for (int i =0; i < n; i++) {z[i]=0;}
	char typ3;
      cout<< "Do you want to price under the forward measure or the risk-neutral? (F/R)";
	cin>> typ3;
if (typ3 == 'F')
  {
	 root->ZTree();
  }
  else
  {
  	root->NTree();
  }
	
//Here various inputs are required to price a security. These cin's can be replaced so the program doesn't ask at every line of interest rates. It is also possible to move to above the while loop, so it is only asked once.  
      //after inputs, the proper fixed income derivative function is called
      
      cout<< "Do you want a cap or floor? (C/F) ";
      //char *types;
      int dep;
      double val;
      char typ;
      cin >> typ;
      cout<< "Do you want a Full derivitive or a Let? (F/L)";
      char typ2;
      cin>> typ2;
      cout<< "What is the year of maturity? ";
      cin>> dep;
      cout<< "What is the rate? ";
      cin >> val;
      if (typ2 == 'L')
	{
	  if (typ == 'C')
	    {
	      //	cout<< 3;
	      //
	      //      cout << typ<< endl;
	      cout<< "The value of the caplet is: "; 
	    }
	  if (typ == 'F')
	    {
	      cout<< "The value of the floorlet is: ";
	    }
	  cout<<root->ValueLet(dep, val, typ, typ3)<<endl;
	}
      if (typ2 == 'F')
	{
	  if (typ == 'C')
            {
              //        cout<< 3;
              //
              //      cout << typ<< endl;
              cout<< "The value of the cap is: ";
            }
          if (typ == 'F')
            {
              cout<< "The value of the floor is: ";
            }
          cout<<root->ValueFull(dep, val, typ, typ3)<<endl;

	}
      
      
  //clear everything
      delete [] a;
      delete [] b;
      delete [] c;
      delete [] buf;
      delete [] tok;
      delete [] root;
 
    }

  return 0;
}

