from abc import ABC, abstractmethod from enum import Enum, unique @unique class DatumType(Enum): FUND = 'FUND' INDEX = 'INDEX' @unique class AssetRiskDateType(Enum): START_DATE = 1 STOP_DATE = 2 @unique class AssetPoolType(Enum): OPTIMIZE = 1 RISK = 2 @unique class PortfoliosRisk(Enum): FT3 = 3 FT6 = 6 FT9 = 9 @unique class PortfoliosType(Enum): CRISIS_1 = 'crisis_1' CRISIS_2 = 'crisis_2' RIGHT_SIDE = 'right_side' NORMAL = 'normal' CUSTOM = 'custom' @unique class SolveType(Enum): INFEASIBLE = 0 MPT = 1 POEM = 2 @unique class SignalType(Enum): INIT = 0 CRISIS_EXP = 1 CRISIS_ONE = 2 CRISIS_TWO = 3 MARKET_RIGHT = 4 HIGH_BUY = 5 LOW_BUY = 6 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 @abstractmethod def get_index_datums(self, ticker=None, index_ids=None): ''' 获取指标资料数据 :param ticker: 指标的彭博ticker :param index_ids: 指标id列表 :return: 即表资料信息 ''' pass @abstractmethod def get_high_risk_datums(self, risk: PortfoliosRisk): ''' 根据指定的投组风险等级,获取高风险资产资料数据 :param risk: 投组风险等级 :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 @abstractmethod def get_index_close(self, datum_ids=None, min_date=None, max_date=None, ticker=None): ''' 获取指标收盘价 :param datum_ids: 指标资料id :param min_date: 起始时间 :param max_date: 截止时间 :param ticker: 指标资料ticker :return: 指标收盘价信息 ''' pass @abstractmethod def get_last_index_close(self, max_date, datum_id=None, ticker=None, count=1): ''' 获取指定资料或ticker,指定日期之前最后count个收盘价,当指定datum_id后,ticker参数无效 :param max_date: 指定日期 :param datum_id: 指标id,只能指定一个 :param ticker: 指标ticker,只能指定一个,当指标id有值后,该参数无效 :param count: 指定要返回数据的个数 :return: 如果存在,则返回指定日期最后count个收盘价,否则返回None ''' 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 class AssetPool(ABC): ''' 资产池相关服务 ''' @abstractmethod def get_pool(self, day): ''' 返回指定日期的可用资产池 :param day: 指定日期 :return: 资产id列表 ''' pass class PortfoliosBuilder(ABC): ''' 投组组合构建器 ''' @abstractmethod def get_portfolios(self, day, risk: PortfoliosRisk, type: PortfoliosType = PortfoliosType.NORMAL): ''' 获取指定日期,指定风险等级,指定类型的投资组合 :param type: 投组的类型 :param day: 指定日期 :param risk: 风险等级 :return: 资产组合字典{id: weight} ''' pass @abstractmethod def build_portfolio(self, day, type: PortfoliosType): ''' 构建指定日期,指定类型的投资组合 :param day: 指定日期 :param type: 指定类型 :return 投资组合数据{risk: {...}},计算明细数据 {...} ''' pass class Solver(ABC): ''' 解算器 ''' def solve_max_rtn(self): ''' :return: max_rtn, max_var, minCVaR_whenMaxR ''' pass def solve_min_rtn(self): ''' :return: min_rtn, min_var, maxCVaR_whenMinR ''' pass def solve_mpt(self, min_rtn, max_rtn): ''' 常规mpt计算 :param min_rtn: 最小回报率 :param max_rtn: 最大回报率 :return: 投组,cvar ''' pass def solve_poem(self, min_rtn, max_rtn, base_cvar, max_cvar): ''' poem方式的mpt计算 :param min_rtn: 最小回报率 :param max_rtn: 最大回报率 :param base_cvar: 基础cvar :param max_cvar: 最大cvar :return: 投组,cvar ''' pass def reset_navs(self, day): ''' 根据指定的日期,重置当前解算器,其他计算,全部依赖这里重置后的基金净值数据 :param day: 指定的日期 :return: 根据指定日期获取的,基金净值数据 ''' pass @property @abstractmethod def navs(self): ''' :return: 当前解算器需要的基金净值 ''' pass class SolverFactory(ABC): ''' 解算器工厂 ''' @abstractmethod def create_solver(self, risk: PortfoliosRisk, type: PortfoliosType = PortfoliosType.NORMAL) -> Solver: pass class SignalBuilder(ABC): ''' 控制信号,发起是否调仓服务 ''' @abstractmethod def get_signal(self, day, risk: PortfoliosRisk): pass