Commit 75416445 authored by 纪超's avatar 纪超

完成日志、配置文件、数据库工具模块

parent 226692af
...@@ -19,6 +19,7 @@ class Datum(ABC): ...@@ -19,6 +19,7 @@ class Datum(ABC):
''' '''
基础资料服务,基金资料数据,各种指数,指标资料数据 基础资料服务,基金资料数据,各种指数,指标资料数据
''' '''
@abstractmethod @abstractmethod
def get_fund_datums(self, crncy=None, risk=None, fund_ids=None): def get_fund_datums(self, crncy=None, risk=None, fund_ids=None):
''' '''
...@@ -35,6 +36,7 @@ class Navs(ABC): ...@@ -35,6 +36,7 @@ class Navs(ABC):
''' '''
基础数据相关服务,基金净值,各种指标 高开低收 基础数据相关服务,基金净值,各种指标 高开低收
''' '''
@abstractmethod @abstractmethod
def get_fund_navs(self, fund_ids=None, min_date=None, max_date=None): def get_fund_navs(self, fund_ids=None, min_date=None, max_date=None):
''' '''
...@@ -47,10 +49,11 @@ class Navs(ABC): ...@@ -47,10 +49,11 @@ class Navs(ABC):
pass pass
class Optimize(ABC): class AssetOptimize(ABC):
''' '''
优选相关服务ABC 优选相关服务ABC
''' '''
@abstractmethod @abstractmethod
def find_optimize(self, ids, day): def find_optimize(self, ids, day):
''' '''
...@@ -71,13 +74,26 @@ class Optimize(ABC): ...@@ -71,13 +74,26 @@ class Optimize(ABC):
pass pass
class EwmaCvar(metaclass=ABCMeta): class AssetRisk(ABC):
''' '''
ewma相关服务 ewma相关服务
''' '''
def build_ewma_cvar(self): @abstractmethod
def get_risk_pool(self, day):
'''
获取指定日期的风控池
:param day: 指定的日期
:return: 风控id列表
'''
pass pass
@abstractmethod
def is_risk(self, id, day) -> bool:
'''
判断指定的id,在指定的日期,是处于风控状态
:param id: 指定的资产id
:param day: 指定的日期
:return: 如果处于风控状态则返回True,否则返回False
'''
pass
...@@ -4,11 +4,11 @@ from abc import ABC, abstractmethod ...@@ -4,11 +4,11 @@ from abc import ABC, abstractmethod
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from empyrical import sortino_ratio from empyrical import sortino_ratio
from framework import filter_weekend, dict_remove, get_config, component, autowired from framework import filter_weekend, dict_remove, get_config, component, autowired
from api import Optimize, Navs, BusinessException, Datum from api import AssetOptimize, Navs, BusinessException, Datum
from fund_pool.dao import robo_optimize_pool as rop from asset_pool.dao import robo_optimize_pool as rop
class SortinoOptimize(Optimize, ABC): class SortinoAssetOptimize(AssetOptimize, ABC):
def __init__(self): def __init__(self):
optimize_config = get_config(__name__) optimize_config = get_config(__name__)
...@@ -65,7 +65,7 @@ class SortinoOptimize(Optimize, ABC): ...@@ -65,7 +65,7 @@ class SortinoOptimize(Optimize, ABC):
@component @component
class FundSortinoOptimize(SortinoOptimize): class FundSortinoAssetOptimize(SortinoAssetOptimize):
''' '''
根据索提诺比率计算基金优选的优选实现 根据索提诺比率计算基金优选的优选实现
''' '''
......
import pandas as pd
from framework import component, autowired, get_config
from api import AssetRisk, Navs
@component
class CvarEwmaAssetRisk(AssetRisk):
'''
CVAR方式决定风控开始
EWMA方式决定风控结束
'''
@autowired
def __init__(self, navs: Navs = None):
self._navs = navs
self._config = get_config(__name__)
def get_risk_pool(self, day):
pass
def is_risk(self, id, day) -> bool:
rtn = self.get_income_return(id, day)
print(rtn)
def get_cvar_start_date(self):
pass
def get_ewma_start_date(self):
pass
def get_income_return(self, id, day):
fund_navs = pd.DataFrame(self._navs.get_fund_navs(fund_ids=id, max_date=day))
fund_navs['rtn'] = fund_navs['nav_cal'] / fund_navs['nav_cal'].shift(self._config['rtn_day']) - 1
fund_navs.dropna(inplace=True)
fund_navs.rename(columns={'nav_date': 'date'}, inplace=True)
fund_navs = fund_navs[['date', 'rtn']]
return fund_navs.to_dict('records')
...@@ -2,11 +2,30 @@ CREATE TABLE IF NOT EXISTS robo_optimize_pool ...@@ -2,11 +2,30 @@ CREATE TABLE IF NOT EXISTS robo_optimize_pool
( (
rop_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, rop_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
rop_date DATETIME NOT NULL COMMENT '数据日期', rop_date DATETIME NOT NULL COMMENT '数据日期',
rop_fund_ids JSON DEFAULT NULL COMMENT '基金ID', rop_type TINYINT NOT NULL COMMENT '资产池类别',
rop_asset_ids JSON DEFAULT NULL COMMENT '基金ID',
rop_create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, rop_create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
rop_update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, rop_update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (rop_id), PRIMARY KEY (rop_id),
UNIQUE INDEX (rop_date) INDEX (rop_date),
INDEX (rop_type)
) ENGINE = InnoDB ) ENGINE = InnoDB
AUTO_INCREMENT = 0 AUTO_INCREMENT = 0
DEFAULT CHARSET = utf8mb4 COMMENT '优选基金池'; DEFAULT CHARSET = utf8mb4 COMMENT '优选基金池';
\ No newline at end of file
CREATE TABLE IF NOT EXISTS asset_risk_dates
(
ard_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
ard_date DATETIME NOT NULL COMMENT '风控日期',
ard_type TINYINT NOT NULL COMMENT '日期类型',
ard_asset_id BIGINT UNSIGNED NOT NULL COMMENT '资产ID',
ard_create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ard_update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (ard_id),
INDEX (ard_date),
INDEX (ard_type),
INDEX (ard_asset_id)
) ENGINE = InnoDB
AUTO_INCREMENT = 0
DEFAULT CHARSET = utf8mb4 COMMENT '资产风控日期表';
\ No newline at end of file
import json
from framework import read, parse_date, where
from api import DatumType from api import DatumType
from framework import read, where, to_tuple
@read @read
...@@ -14,6 +13,4 @@ def get_one(*args, **kwargs): ...@@ -14,6 +13,4 @@ def get_one(*args, **kwargs):
def get_base_datums(type: DatumType = None, crncy=None, risk=None, fund_ids=None): def get_base_datums(type: DatumType = None, crncy=None, risk=None, fund_ids=None):
fund_ids = tuple(fund_ids) if fund_ids else None return get_list(rbd_id=to_tuple(fund_ids), v_rbd_type=type, v_rbd_crncy=crncy, v_rbd_risk=risk)
return get_list(rbd_id=fund_ids, v_rbd_type=type, v_rbd_crncy=crncy, v_rbd_risk=risk)
from framework import read, where, format_date from framework import read, where, format_date, to_tuple
@read @read
...@@ -17,5 +17,4 @@ def get_navs(fund_id=None, min_date=None, max_date=None): ...@@ -17,5 +17,4 @@ def get_navs(fund_id=None, min_date=None, max_date=None):
sqls.append(f"rfn_date >= '{format_date(min_date)}'") sqls.append(f"rfn_date >= '{format_date(min_date)}'")
if max_date: if max_date:
sqls.append(f"rfn_date <= '{format_date(max_date)}'") sqls.append(f"rfn_date <= '{format_date(max_date)}'")
fund_id = tuple(fund_id) if fund_id else None return get_list(*sqls, rfn_fund_id=to_tuple(fund_id))
return get_list(*sqls, rfn_fund_id=fund_id)
...@@ -27,6 +27,10 @@ class DefaultNavs(Navs): ...@@ -27,6 +27,10 @@ class DefaultNavs(Navs):
navs = navs.reset_index().melt(id_vars='nav_date', value_name='nav_cal') navs = navs.reset_index().melt(id_vars='nav_date', value_name='nav_cal')
navs.dropna(inplace=True) navs.dropna(inplace=True)
navs = navs[['fund_id', 'nav_date', 'nav_cal']] navs = navs[['fund_id', 'nav_date', 'nav_cal']]
navs.sort_values('fund_id', inplace=True) navs.sort_values(by=['fund_id', 'nav_date'], inplace=True)
navs = navs.to_dict('records') navs = navs.to_dict('records')
return navs return navs
if __name__ == '__main__':
print(isinstance((), tuple))
...@@ -51,8 +51,8 @@ basic: ...@@ -51,8 +51,8 @@ basic:
exrate: exrate:
- from: EUR - from: EUR
ticker: EURUSD BGN Curncy ticker: EURUSD BGN Curncy
fund_pool: asset_pool:
fund_optimize: asset_optimize:
sortino_weight: sortino_weight:
- months: 3 - months: 3
weight: 0.5 weight: 0.5
...@@ -60,5 +60,7 @@ fund_pool: ...@@ -60,5 +60,7 @@ fund_pool:
weight: 0.2 weight: 0.2
- years: 1 - years: 1
weight: 0.2 weight: 0.2
asset_risk:
rtn_day: 5
...@@ -7,6 +7,7 @@ __all__ = [ ...@@ -7,6 +7,7 @@ __all__ = [
'dict_remove', 'dict_remove',
'equals_ignore_case', 'equals_ignore_case',
'to_bool', 'to_bool',
'to_tuple',
] ]
...@@ -60,3 +61,11 @@ def to_bool(v) -> bool: ...@@ -60,3 +61,11 @@ def to_bool(v) -> bool:
if reduce(lambda a, b: a or b, [equals_ignore_case(v, x) for x in _FALSE_STR]): if reduce(lambda a, b: a or b, [equals_ignore_case(v, x) for x in _FALSE_STR]):
return False return False
return bool(v) return bool(v)
def to_tuple(v) -> tuple:
if isinstance(v, tuple):
return v
if isinstance(v, list):
return tuple(v)
return (v,) if v else None
...@@ -128,8 +128,9 @@ def where(*args, **kwargs) -> str: ...@@ -128,8 +128,9 @@ def where(*args, **kwargs) -> str:
result.append(f"{k} = '{format_date(v)}'") result.append(f"{k} = '{format_date(v)}'")
elif isinstance(v, Enum): elif isinstance(v, Enum):
result.append(f"{k} = '{v.value}'") result.append(f"{k} = '{v.value}'")
elif isinstance(v, tuple): elif isinstance(v, tuple) or isinstance(v, list):
result.append(f"{k} in {v}" if len(v) > 1 else f"{k} = {v[0]}") if len(v) > 0:
result.append(f"{k} in {tuple(v)}" if len(v) > 1 else f"{k} = {v[0]}")
elif v is not None: elif v is not None:
result.append(f"{k} = {v}") result.append(f"{k} = {v}")
if args: if args:
......
from framework import autowired, parse_date, logger from framework import autowired, parse_date, logger
from api import Optimize from api import AssetOptimize, AssetRisk
@autowired @autowired
def start(optimize: Optimize = None): def start(optimize: AssetOptimize = None, risk: AssetRisk = None):
pool = optimize.get_optimize_pool(parse_date('2022-11-07')) # pool = optimize.get_optimize_pool(parse_date('2022-11-07'))
logger.info(pool) # logger.info(pool)
risk.is_risk(1, parse_date('2022-11-07'))
if __name__ == '__main__': if __name__ == '__main__':
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment