from abc import ABC, abstractmethod
from enum import Enum, unique


@unique
class DatumType(Enum):
    FUND = 'FUND'


class BusinessException(Exception):
    def __init__(self, msg):
        self.__msg = msg

    def __str__(self):
        return self.__msg


class Datum(ABC):
    '''
    基础资料服务,基金资料数据,各种指数,指标资料数据
    '''

    @abstractmethod
    def get_fund_datums(self, crncy=None, risk=None, fund_ids=None):
        '''
        获取基金资料数据
        :param crncy: 货币类型
        :param risk: 风险等级,e.g: 1-5
        :param fund_ids: 基金ID列表
        :return:基金资料信息
        '''
        pass


class Navs(ABC):
    '''
    基础数据相关服务,基金净值,各种指标 高开低收
    '''

    @abstractmethod
    def get_fund_navs(self, fund_ids=None, min_date=None, max_date=None):
        '''
        获取基金净值信息
        :param fund_ids: 基金id,可以多个id,使用tuple包裹
        :param min_date: 起始时间
        :param max_date: 截止时间
        :return: 基金净值信息
        '''
        pass


class AssetOptimize(ABC):
    '''
    优选相关服务ABC
    '''

    @abstractmethod
    def find_optimize(self, ids, day):
        '''
        从多id中,选出指定日期最优的id
        :param ids: 待选id列表
        :param day: 指定日期
        :return: 最优的id
        '''
        pass

    @abstractmethod
    def get_optimize_pool(self, day):
        '''
        根据优选规则获取指定日期的优选池
        :param day: 指定日期
        :return: 优选id列表
        '''
        pass


class AssetRisk(ABC):
    '''
    ewma相关服务
    '''

    @abstractmethod
    def get_risk_pool(self, day):
        '''
        获取指定日期的风控池
        :param day: 指定的日期
        :return: 风控id列表
        '''
        pass

    @abstractmethod
    def is_risk(self, id, day) -> bool:
        '''
        判断指定的id,在指定的日期,是处于风控状态
        :param id: 指定的资产id
        :param day: 指定的日期
        :return: 如果处于风控状态则返回True,否则返回False
        '''
        pass