# Copyright (C) 2016 EDF
# All Rights Reserved
# This code is published under the GNU Lesser General Public License (GNU LGPL)
import math
import numpy as np
import unittest
import StOptGrids 
import StOptReg
import StOptGlobal
import Utils
import Simulators as sim
import dp.DynamicProgrammingByRegression as dyn
import dp.FinalValueFictitiousFunction as fvff
import dp.OptimizeFictitiousSwing as OptimizeFictitiousSwing
import utils.BasketOptions as bo

accuracyClose = 1.5


class testSwingOptimSimuNDTest(unittest.TestCase) :
    
    def test_resolutionSwingOptimSimu(self):
    
        ndim = 2
        initialValues = np.zeros(1) + 1.
        sigma = np.zeros(1) + 0.2
        mu = np.zeros(1) + 0.05
        corr = np.ones((1,1))
        # number of step
        nStep = 20
        # exercise date
        dates = np.linspace(0., 1., nStep + 1)
        N = 3 # number of exercises
        T = 1.
        strike = 1.
        nbSimul = 80000
        nMesh = 8
        # payoff for swing
        payOffBasket = bo.BasketCall(strike)
        nbMesh = np.zeros(1, dtype = np.int32) + nMesh
        # simulator
        simulatorBack = sim.BlackScholesSimulator(initialValues, sigma, mu, corr, dates[len(dates) - 1], len(dates) - 1, nbSimul, False)
        # Grid
        lowValues = np.zeros(ndim)
        step = np.zeros(ndim) + 1.
        nbStep = np.zeros(ndim, dtype = np.int32) + N
        grid =  StOptGrids.RegularSpaceGrid(lowValues, step, nbStep)
        vFunction = fvff.FinalValueFictitiousFunction(payOffBasket, N)
        # optimizer
        actu = math.exp(-mu[0] * T / nStep)
        optimizer = OptimizeFictitiousSwing.OptimizeFictitiousSwing(payOffBasket, N, ndim, actu)
        # initial values
        initialStock = np.zeros(ndim)
        initialRegime = 0
        fileToDump = "CondExpSwingOptimND"
        # regressor
        regressor = StOptReg.LocalLinearRegression(nbMesh)
        # link the simulations to the optimizer
        optimizer.setSimulator(simulatorBack)
        # bermudean value
        valueOptim = dyn.DynamicProgrammingByRegression(grid, optimizer, regressor, vFunction, initialStock, initialRegime, fileToDump)
        print("Optim", valueOptim)
        
if __name__ == '__main__':
    unittest.main()
