!!------------------------------------------------------------------------
! $Id: american_mc.f90,v 1.2 1997/11/12 13:30:40 scott Exp $
!!Written by Scott A. Klasky
!!Copyright Scott A. Klasky, Geoffrey Fox, Mike Boughton, Scott McGuire
!! and NPAC, Syracuse University
!!Program to calculate American options
!!
!!First attempt: 10,19,1997-
!!Modified 10/21/1997 by Scott V. McGuire
!!   NOTES: Limitations on this program include the following:
!!          Only made to work with 1 underlying (will change data structures
!!          later).
!!------------------------------------------------------------------------

!! Want to define the Data structure before we begin, because this will 
!! make it much easier to code with the proper data structure.

program american
  use PATHS
  use MOD_INT
  use input_params
  implicit none

  type (PATH),dimension(:,:),save,allocatable    :: eta,sorteta

  real*8,dimension(:,:),save,allocatable         :: payoff, stockprice
  real*8,dimension(:,:),save,allocatable         :: sortpayoff 
  integer,dimension(:,:),save,allocatable        :: sort_order

  integer                                        :: max_nn
  integer                                        :: max_iter
  integer                                        :: ntime, npath, nn
  integer                                        :: tl, ol, iter, otl
  integer,parameter                              :: max_params = 30
  real*8,dimension(max_params)                   :: params
  character*10,parameter                         :: fname="path.stock"
  real*8                                         :: total_energy

  real*8                                         :: energy, oldenergy
  real*8                                         :: newenergy,oldpe,oldke,newpe
  real*8                                         :: newke,deltae
  real*8                                         :: spin_new 
  real*8                                         :: r1
  real*8,parameter                               :: HALF = 0.5d0
  integer,parameter                              :: SEED = 100

  real*8                                         :: paymax,pay1d
  real*8,dimension(:),save,allocatable           :: min_energy 
  real*8                                         :: temp
  integer                                        :: anealing
  integer                                        :: tnum
  integer                                        :: flips
  integer                                        :: annealing
  real*8                                         :: r,sss
  integer                                        :: i,j
  integer                                        :: jiter, ool, j1iter, olsave
  integer                                        :: accept,reject 
  real*8                                         :: avgpayoff
  integer                                        :: spin_total,ispin
  integer                                        :: olstart

  !! read in the parameters (Stock Price, Strike price, etc.
  !! read in the data from the european MC code
  !! Next sort the list in the Stock Price Dimension
  !! Next find the nearest neighbor list
  !! Set up the initial spins
  !! Find the initial energy of the system

	

  call random_seed(SEED)

  call read_params(max_params,params)

  !! allocate the memory
  ntime = int(params(P_NTIME))
  npath = int(params(P_NPATH))
  nn    = int(params(P_NNN))

  allocate ( eta(ntime,npath),sorteta(ntime,npath) ) 
  allocate ( payoff(ntime,npath) ) 
  allocate ( stockprice(ntime,npath) ) 
  allocate ( sort_order(ntime,npath) )
  allocate ( sortpayoff(ntime,npath) )

  do  tl = 1 , ntime 
     do ol = 1 , npath 
        allocate(eta(tl,ol)%nns(nn)) 
        allocate(eta(tl,ol)%nng(nn)) 
        allocate(eta(tl,ol)%nnt(nn)) 
        allocate(eta(tl,ol)%nni(nn)) 
        allocate(eta(tl,ol)%nnj(nn)) 
        allocate(sorteta(tl,ol)%nns(nn)) 
        allocate(sorteta(tl,ol)%nng(nn)) 
        allocate(sorteta(tl,ol)%nnt(nn)) 
        allocate(sorteta(tl,ol)%nni(nn)) 
        allocate(sorteta(tl,ol)%nnj(nn)) 
     end do !ol
  end do !tl

  allocate (min_energy(int(params(P_ANNEALS))))

  call read_data(fname,max_params,params,stockprice)
  open(20,file='am.out')

  write(20,*) 'input parameters:'
  do tl = 1, max_params
     write(20,*) tl,params(tl)
  end do

  call sort_stock(max_params,params,stockprice,sort_order,payoff)
  call calculate_payoff(max_params,params,payoff,sortpayoff)
  call find_nearest_neighbor_list(max_params,params,sortpayoff,eta)
  call initialize_spins(max_params,params,sortpayoff,eta)

  avgpayoff = sorted_average_payoff(max_params,params,sortpayoff,eta,sort_order)

  jiter = 0

!   do otl = int(params(P_NTIME))-1, int(params(P_NTIME))-1,-1 
     do otl = int(params(P_NTIME))-1, 1,-1 
		write(6,*) otl

 		olstart = int(params(P_NPATH))
  
		eta(1:otl-1,:)%spin = 0
		eta(otl,:)%spin = 1

    paymax=-999.99d99 
!sorted_laverage_payoff(otl,max_params,params,sortpayoff,   &
!                                  eta,sort_order)
		olsave = params(P_NPATH)+1  !this is where the first one is

      do ol = olstart,1,-1
         eta(otl,ol:npath)%spin = 0
         pay1d=sorted_laverage_payoff(otl,max_params,params,sortpayoff,   &
                                      eta,sort_order)
         if (pay1d > paymax) then
            ! keep this spin
            paymax = pay1d
				olsave = ol
			end if
		end do !ol
    write(6,*) 'olsave=',olsave


		eta(otl,:)%spin = 0
		eta(otl,1:olsave-1)%spin = 1

		
	end do !otl
write(6,*) 'done'
   paymax=sorted_average_payoff(max_params,params,sortpayoff,   &
                               eta,sort_order)
 	   call dump_dat1d("Boundary",otl,1.0d0*(ntime-otl),max_params,params, &
                      sortpayoff,eta)
	write(6,*) paymax
	write(20,*) paymax
!   call dump_data("eta",1.0d0,max_params,params,eta)
  close(20)

end program american
