#!/user/bin/env python
# -*- coding: utf-8 -*-
"""
Copyright (C) 2024 Galaxy Technologies
Licensed under the Apache License, Version 2.0
"""
import numpy as np
from pricelib.common.pricing_engine_base import McEngine
from pricelib.common.date_handler import global_evaluation_date


class MCPortfolioEngine(McEngine):
    """香草组合 Monte Carlo 模拟定价引擎"""

    def calc_present_value(self, prod, t=None, spot=None):
        """计算现值
        Args:
            prod: Product产品对象
            t: datetime.date，估值日; 如果是None，则使用全局估值日globalEvaluationDate
            spot: float，估值日标的价格，如果是None，则使用随机过程的当前价格
        Returns: float，现值
                        如果输入spot = np.ndarray一维价格向量，t=终止日，则返回盈亏测算向量，即每个价格对应的现值，而不是平均值
        """
        calculate_date = global_evaluation_date() if t is None else t
        _maturity = (prod.end_date - calculate_date).days / prod.annual_days.value
        n_step = round(_maturity * prod.t_step_per_year)
        if spot is None:
            spot = self.process.spot()
        # 当估值日就是到期日时，直接用spot计算payoff，无需随机数矩阵
        if calculate_date == prod.end_date:
            if isinstance(spot, (list, np.ndarray)):  # spot是一个np.ndarray一维价格向量，返回盈亏测算向量，即每个价格对应的现值，而不是平均值
                paths = np.array([spot, ])
            else:  # spot是一个数值，计算期末payoff
                paths = np.array([[spot, ]])
        else:
            if spot != self.process.spot():
                self.reset_paths_flag()  # 重置路径标志位，重新生成路径
            paths = self.path_generator(n_step=n_step, spot=spot, t_step_per_year=prod.t_step_per_year).copy()

        price = 0
        for vanilla, position in prod.vanilla_list:
            price += (np.maximum(vanilla.callput.value * (paths[-1, :] - vanilla.strike),
                                        0)) * position * self.process.interest.disc_factor(_maturity)

        if (calculate_date == prod.end_date) and isinstance(spot, np.ndarray):
            return price  # 终止日, spot是价格向量, 则返回盈亏测算向量，即每个价格对应的现值，而不是平均值
        else:
            return np.mean(price)
