Commit 42c68afc authored by jichao's avatar jichao

依赖注入实现中

parent 8f75bef3
from framework import parse_date, get_quarter_start, get_config
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from enum import Enum, unique from enum import Enum, unique
from dateutil.relativedelta import relativedelta
@unique @unique
...@@ -7,6 +9,19 @@ class DatumType(Enum): ...@@ -7,6 +9,19 @@ class DatumType(Enum):
FUND = 'FUND' FUND = 'FUND'
@unique
class AssetRiskDateType(Enum):
START_DATE = 1
STOP_DATE = 2
@unique
class AssetPoolType(Enum):
OPTIMIZE = 1
RISK = 2
class BusinessException(Exception): class BusinessException(Exception):
def __init__(self, msg): def __init__(self, msg):
self.__msg = msg self.__msg = msg
...@@ -97,3 +112,17 @@ class AssetRisk(ABC): ...@@ -97,3 +112,17 @@ class AssetRisk(ABC):
:return: 如果处于风控状态则返回True,否则返回False :return: 如果处于风控状态则返回True,否则返回False
''' '''
pass pass
class AssetPool(ABC):
'''
资产池相关服务
'''
@abstractmethod
def get_pool(self, day):
'''
返回指定日期的可用资产池
:param day: 指定日期
:return: 资产id列表
'''
pass
...@@ -3,9 +3,10 @@ import pandas as pd ...@@ -3,9 +3,10 @@ import pandas as pd
from abc import ABC, abstractmethod 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, get_quarter_start
from api import AssetOptimize, Navs, BusinessException, Datum from api import AssetOptimize, Navs, BusinessException, Datum, AssetPoolType
from asset_pool.dao import robo_optimize_pool as rop from asset_pool.dao import robo_assets_pool as rop
from datetime import datetime as dt
class SortinoAssetOptimize(AssetOptimize, ABC): class SortinoAssetOptimize(AssetOptimize, ABC):
...@@ -15,7 +16,7 @@ class SortinoAssetOptimize(AssetOptimize, ABC): ...@@ -15,7 +16,7 @@ class SortinoAssetOptimize(AssetOptimize, ABC):
self._config = [{ self._config = [{
**x, **x,
'name': [f"sortino_{y[1]}_{y[0]}" for y in x.items() if y[0] != 'weight'][0] 'name': [f"sortino_{y[1]}_{y[0]}" for y in x.items() if y[0] != 'weight'][0]
} for x in optimize_config['sortino_weight']] if 'sortino_weight' in optimize_config else [] } for x in optimize_config['sortino-weight']] if 'sortino-weight' in optimize_config else []
def find_optimize(self, fund_ids, day): def find_optimize(self, fund_ids, day):
if not self._config: if not self._config:
...@@ -34,17 +35,18 @@ class SortinoAssetOptimize(AssetOptimize, ABC): ...@@ -34,17 +35,18 @@ class SortinoAssetOptimize(AssetOptimize, ABC):
return pct_change.columns[sortino.index[0]] return pct_change.columns[sortino.index[0]]
def get_optimize_pool(self, day): def get_optimize_pool(self, day):
last_one = rop.get_last_one(day) last_one = rop.get_last_one(day=day, type=AssetPoolType.OPTIMIZE)
if not last_one: start = get_quarter_start(day or dt.today())
if not last_one or start > last_one['date']:
pool = [] pool = []
for fund_group in self.get_groups(): for fund_group in self.get_groups():
if len(fund_group) > 1: if len(fund_group) > 1:
pool.append(self.find_optimize(fund_group, day)) pool.append(self.find_optimize(fund_group, day))
else: else:
pool.append(fund_group[0]) pool.append(fund_group[0])
rop.insert(day, sorted(pool)) rop.insert(day, AssetPoolType.OPTIMIZE, sorted(pool))
last_one = rop.get_last_one(day) last_one = rop.get_last_one(day=day, type=AssetPoolType.OPTIMIZE)
return json.loads(last_one['fund_ids']) return json.loads(last_one['asset_ids'])
@abstractmethod @abstractmethod
def get_groups(self): def get_groups(self):
......
from framework import component, autowired
from api import AssetPool, AssetOptimize, AssetRisk
from datetime import datetime as dt
@component
class FundAssetPool(AssetPool):
@autowired
def __init__(self, optimize: AssetOptimize = None, risk: AssetRisk = None):
self._optimize = optimize
self._risk = risk
def get_pool(self, day=dt.today()):
opti_pool = self._optimize.get_optimize_pool(day)
risk_pool = self._risk.get_risk_pool(day)
return [x for x in opti_pool if x not in risk_pool]
\ No newline at end of file
import time
import traceback
import pandas as pd import pandas as pd
from framework import component, autowired, get_config import json
from api import AssetRisk, Navs from scipy.stats import norm
from datetime import datetime as dt
from dateutil.relativedelta import relativedelta
from framework import component, autowired, get_config, log, format_date
from api import AssetRisk, Navs, AssetRiskDateType as DateType, Datum, AssetPoolType
from asset_pool.dao import asset_risk_dates as ard, asset_ewma_value as aev, robo_assets_pool as rap
from concurrent.futures import ProcessPoolExecutor, wait, as_completed
def get_risk_start_date():
config = get_config("main")
return config['start-date'] - relativedelta(months=3)
def test(*args, **kwargs):
print(args, kwargs)
@component @component
class CvarEwmaAssetRisk(AssetRisk): class CvarEwmaAssetRisk(AssetRisk):
''' '''
CVAR方式决定风控开始 CVAR方式决定风控开始。风控开始后,开始计算ewma寻找风控结束日期,也就是ewma的起始日期
EWMA方式决定风控结束 EWMA方式决定风控结束:风控结束后,就可以找到风控期的最低点日期,该日期作为下一轮cvar计算的起始日期
''' '''
@autowired @autowired
def __init__(self, navs: Navs = None): def __init__(self, navs: Navs = None, datum: Datum = None):
self._navs = navs self._navs = navs
self._datum = datum
self._config = get_config(__name__) self._config = get_config(__name__)
def get_risk_pool(self, day): def get_risk_pool(self, day):
pass asset_pool = rap.get_one(day, AssetPoolType.RISK)
if not asset_pool:
with ProcessPoolExecutor(max_workers=4) as process:
futures = {process.submit(self.is_risk, x['id'], day): x for x in self._datum.get_fund_datums()}
risk_ids = [futures[x]['id'] for x in as_completed(futures) if x.result()]
rap.insert(day, AssetPoolType.RISK, risk_ids)
asset_pool = rap.get_one(day, AssetPoolType.RISK)
return json.loads(asset_pool['asset_ids'])
def is_risk(self, id, day) -> bool: def is_risk(self, id, day) -> bool:
rtn = self.get_income_return(id, day) asset_pool = rap.get_one(day, AssetPoolType.RISK)
print(rtn) if asset_pool:
return id in json.loads(asset_pool['asset_ids'])
self.build_risk_date(id, day)
last = ard.get_last_one(id, day)
return DateType(last['type']) is DateType.START_DATE if last else False
def get_cvar_start_date(self): def build_risk_date(self, asset_id, day=None):
pass risk_date = "first"
try:
log.debug(f"start build risk date for asset[{asset_id}] to date[{format_date(day)}]")
while risk_date is not None:
risk_date = self.get_next_date(asset_id, day=day)
except Exception as e:
log.exception(f"build risk date for asset[{asset_id}] after date[{risk_date}] error", e)
def get_ewma_start_date(self): def get_next_date(self, asset_id, day=dt.today()):
pass last = ard.get_last_one(asset_id, day)
if not last or DateType(last['type']) is DateType.START_DATE:
start_date = last['date'] if last else get_risk_start_date()
ewma = pd.DataFrame(self.get_ewma_value(asset_id, min_date=start_date, max_date=day))
total = self._config['ewma']['condition-total']
meet = self._config['ewma']['condition-meet']
threshold = self._config['ewma']['threshold']
if len(ewma) < total:
return None
for index in range(total, len(ewma) - 1):
sub_ewma = ewma[index - total:index]
if len(sub_ewma[sub_ewma['ewma'] >= threshold]) >= meet:
stop_date = sub_ewma.iloc[-1]['date']
ard.insert(asset_id, DateType.STOP_DATE, stop_date)
return {'date': stop_date, 'type': DateType.STOP_DATE}
elif DateType(last['type']) is DateType.STOP_DATE:
last_start = ard.get_last_one(asset_id, last['date'], type=DateType.START_DATE)
start_date = last_start['date'] if last_start else get_risk_start_date()
rtns = pd.DataFrame(self.get_income_return(asset_id, min_date=start_date, max_date=day))
risk_rtns = rtns[rtns.date <= last['date']]
cvar_start_date = risk_rtns.loc[risk_rtns.rtn.idxmin()].date
for index, row in rtns[rtns.date >= cvar_start_date].iterrows():
tigger = False
cvar_rtns = rtns[(rtns.date >= cvar_start_date) & (rtns.date <= row['date'])]
if row['rtn'] < rtns[rtns.date == cvar_start_date].iloc[0].rtn:
# 当日回报率跌破最低点, 则直接触发
tigger = True
elif row['rtn'] <= self._config['cvar']['threshold'] and len(cvar_rtns) >= self._config['cvar']['min-volume']:
# 当日回报率小于等于阀值并且有足够cvar累计计算数据,则计算cvar判断
alpha = 1 - self._config['cvar']['coef']
mean = cvar_rtns['rtn'].mean()
std = cvar_rtns['rtn'].std()
cvar = mean - std * norm.pdf(norm.ppf(alpha)) / alpha
tigger = row['rtn'] < cvar
if tigger:
ard.insert(asset_id, DateType.START_DATE, row['date'])
return {'date': row['date'], 'type': DateType.START_DATE}
return None
def get_income_return(self, id, day): def get_ewma_value(self, id, min_date=get_risk_start_date(), max_date=None):
fund_navs = pd.DataFrame(self._navs.get_fund_navs(fund_ids=id, max_date=day)) rtn = pd.DataFrame(self.get_income_return(id, min_date=min_date, max_date=max_date))
fund_navs['rtn'] = fund_navs['nav_cal'] / fund_navs['nav_cal'].shift(self._config['rtn_day']) - 1 if rtn.empty:
return []
rtn.sort_values('date', inplace=True)
last_one = aev.get_last_one(id, max_date=max_date)
if not last_one:
aev.insert(asset_id=id, date=rtn.iloc[0].date, value=rtn.iloc[0].rtn)
last_one = aev.get_last_one(id, max_date=max_date)
last_day = last_one['date']
if last_day < max_date:
ewma = last_one['value']
factor = self._config['ewma']['factor']
for index, row in rtn[rtn['date'] > last_day].iterrows():
ewma = factor * row['rtn'] + (1 - factor) * ewma
aev.insert(id, row['date'], ewma)
result = aev.get_list(id, min_date=min_date, max_date=max_date)
return [{'date': x['date'], 'ewma': x['value']} for x in result]
def get_income_return(self, asset_id, min_date=None, max_date=None):
fund_navs = pd.DataFrame(self._navs.get_fund_navs(fund_ids=asset_id, max_date=max_date))
fund_navs['rtn'] = fund_navs['nav_cal'] / fund_navs['nav_cal'].shift(self._config['rtn-day']) - 1
fund_navs.dropna(inplace=True) fund_navs.dropna(inplace=True)
if min_date:
fund_navs = fund_navs[fund_navs.nav_date >= pd.to_datetime(min_date)]
fund_navs.rename(columns={'nav_date': 'date'}, inplace=True) fund_navs.rename(columns={'nav_date': 'date'}, inplace=True)
fund_navs = fund_navs[['date', 'rtn']] fund_navs = fund_navs[['date', 'rtn']]
return fund_navs.to_dict('records') return fund_navs.to_dict('records')
@autowired
def build_date_task(id, day=dt.today(), asset_risk: CvarEwmaAssetRisk = None):
asset_risk.build_risk_date(id, day)
\ No newline at end of file
from framework import read, write, where, format_date
__COLUMNS__ = {
'aev_id': 'id',
'aev_date': 'date',
'aev_asset_id': 'asset_id',
'aev_value': 'value',
}
@write
def insert(asset_id, date, value):
return f'''
insert into asset_ewma_value(aev_date, aev_asset_id, aev_value)
values ('{format_date(date)}', {asset_id}, {value})
'''
@read(one=True)
def get_last_one(asset_id, max_date=None):
sqls = []
if max_date:
sqls.append(f"aev_date <= '{format_date(max_date)}'")
return f'''
select {','.join([f"{x[0]} as {x[1]}" for x in __COLUMNS__.items()])} from asset_ewma_value
{where(*sqls, aev_asset_id=asset_id)} order by aev_date desc limit 1
'''
@read
def get_list(asset_id, min_date=None, max_date=None):
sqls =[]
if min_date:
sqls.append(f"aev_date >= '{format_date(min_date)}'")
if max_date:
sqls.append(f"aev_date <= '{format_date(max_date)}'")
return f'''select {','.join([f"{x[0]} as {x[1]}" for x in __COLUMNS__.items()])} from asset_ewma_value {where(*sqls, aev_asset_id=asset_id)}'''
@read
def get_last(asset_id, max_date=None, limit=1):
sqls = []
if max_date:
sqls.append(f"aev_date <= '{format_date(max_date)}'")
return f'''
select {','.join([f"{x[0]} as {x[1]}" for x in __COLUMNS__.items()])} from asset_ewma_value
{where(*sqls, aev_asset_id=asset_id)} order by aev_date desc limit {limit}
'''
from framework import read, write, where, format_date
from api import AssetRiskDateType as DateType
__COLUMNS__ = {
'ard_id': 'id',
'ard_date': 'date',
'ard_type': 'type',
'ard_asset_id': 'asset_id',
}
@write
def insert(asset_id, type: DateType, date):
return f'''
insert into asset_risk_dates(ard_asset_id, ard_type, ard_date)
values ({asset_id}, {type.value}, '{format_date(date)}')
'''
@read(one=True)
def get_last_one(fund_id, date, type: DateType = None):
kwargs = {
'ard_asset_id': fund_id,
'ard_type': type.value if type is not None else None
}
sql = f"ard_date <= '{format_date(date)}'" if date else None
return f'''
select {','.join([f"`{x[0]}` as `{x[1]}`" for x in __COLUMNS__.items()])}
from asset_risk_dates {where(sql, **kwargs)} order by ard_date desc, ard_type asc limit 1
'''
CREATE TABLE IF NOT EXISTS robo_optimize_pool CREATE TABLE IF NOT EXISTS robo_assets_pool
( (
rop_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, rap_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
rop_date DATETIME NOT NULL COMMENT '数据日期', rap_date DATETIME NOT NULL COMMENT '数据日期',
rop_type TINYINT NOT NULL COMMENT '资产池类别', rap_type TINYINT NOT NULL COMMENT '资产池类别',
rop_asset_ids JSON DEFAULT NULL COMMENT '基金ID', rap_asset_ids JSON DEFAULT NULL COMMENT '基金ID',
rop_create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, rap_create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
rop_update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, rap_update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (rop_id), PRIMARY KEY (rap_id),
INDEX (rop_date), UNIQUE INDEX (rap_date, rap_type),
INDEX (rop_type) INDEX (rap_type)
) ENGINE = InnoDB ) ENGINE = InnoDB
AUTO_INCREMENT = 0 AUTO_INCREMENT = 0
DEFAULT CHARSET = utf8mb4 COMMENT '优选基金池'; DEFAULT CHARSET = utf8mb4 COMMENT '资产池';
CREATE TABLE IF NOT EXISTS asset_risk_dates CREATE TABLE IF NOT EXISTS asset_risk_dates
...@@ -28,4 +28,20 @@ CREATE TABLE IF NOT EXISTS asset_risk_dates ...@@ -28,4 +28,20 @@ CREATE TABLE IF NOT EXISTS asset_risk_dates
INDEX (ard_asset_id) INDEX (ard_asset_id)
) 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_ewma_value
(
aev_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
aev_date DATETIME NOT NULL COMMENT '日期',
aev_asset_id BIGINT UNSIGNED NOT NULL COMMENT '资产ID',
aev_value DOUBLE NOT NULL COMMENT 'ewma值',
aev_create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
aev_update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (aev_id),
UNIQUE INDEX (aev_asset_id, aev_date),
INDEX (aev_date)
) ENGINE = InnoDB
AUTO_INCREMENT = 0
DEFAULT CHARSET = utf8mb4 COMMENT '资产EWMA数据';
\ No newline at end of file
import json
from framework import read, write, where, format_date
from api import AssetPoolType
__COLUMNS__ = {
'rap_id': 'id',
'rap_date': 'date',
'rap_type': 'type',
'rap_asset_ids': 'asset_ids',
}
@read(one=True)
def get_one(day, type: AssetPoolType):
return f'''select {','.join([f"`{x[0]}` as `{x[1]}`" for x in __COLUMNS__.items()])} from robo_assets_pool {where(rap_date=day, rap_type=type)}'''
@read(one=True)
def get_last_one(type: AssetPoolType = None, day=None):
sql = f"rap_date <= '{format_date(day)}'" if day else None
return f'''select {','.join([f"`{x[0]}` as `{x[1]}`" for x in __COLUMNS__.items()])} from robo_assets_pool {where(sql, rap_type=type)} order by rap_date desc limit 1'''
@write
def insert(day, type: AssetPoolType, pool: list):
return f'''
insert into robo_assets_pool(rap_date, rap_type, rap_asset_ids)
values ('{format_date(day)}', {type.value},'{json.dumps(pool)}')
'''
import json
from framework import read, write, where, format_date
__COLUMNS__ = {
'rop_id': 'id',
'rop_date': 'date',
'rop_fund_ids': 'fund_ids',
}
@read
def get_list(*args, **kwargs):
return f'''select {','.join([f"`{x[0]}` as `{x[1]}`" for x in __COLUMNS__.items()])} from robo_optimize_pool {where(*args, **kwargs)}'''
@read(one=True)
def get_one(*args, **kwargs):
return f'''select {','.join([f"`{x[0]}` as `{x[1]}`" for x in __COLUMNS__.items()])} from robo_optimize_pool {where(*args, **kwargs)}'''
@read(one=True)
def get_last_one(day=None):
sql = f"rop_date <= '{format_date(day)}'" if day else None
return f'''select {','.join([f"`{x[0]}` as `{x[1]}`" for x in __COLUMNS__.items()])} from robo_optimize_pool {where(sql)} order by rop_date desc limit 1'''
@write
def insert(day, pool):
return f'''
insert into robo_optimize_pool(rop_date, rop_fund_ids)
values ('{format_date(day)}', '{json.dumps(pool) if isinstance(pool, dict) else pool}')
'''
...@@ -3,14 +3,11 @@ from framework import read, where, to_tuple ...@@ -3,14 +3,11 @@ from framework import read, where, to_tuple
@read @read
def get_list(*args, **kwargs):
return f'''select rbd_id as id, rbd_datas as datas from robo_base_datum {where(*args, **kwargs)}'''
@read(one=True)
def get_one(*args, **kwargs):
return f'''select rbd_id as id, rbd_datas as datas from robo_base_datum {where(*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):
return get_list(rbd_id=to_tuple(fund_ids), v_rbd_type=type, v_rbd_crncy=crncy, v_rbd_risk=risk) kwargs = {
'rbd_id': to_tuple(fund_ids),
'v_rbd_type': type,
'v_rbd_crncy': crncy,
'v_rbd_risk': risk
}
return f'''select rbd_id as id, rbd_datas as datas from robo_base_datum {where(**kwargs)}'''
from framework import read, where, format_date from framework import read, where, format_date
__COLUMNS__ = {
@read 're_id': 'id',
def get_list(*args, **kwargs): 're_ticker': 'ticker',
return f'''select re_id as id, re_ticker as ticker, re_date as date, re_close as close from robo_exrate {where(*args, **kwargs)}''' 're_date': 'date',
're_close': 'close',
}
@read(one=True)
def get_one(*args, **kwargs):
return f'''select re_id as id, re_ticker as ticker, re_date as date, re_close as close from robo_exrate {where(*args, **kwargs)}'''
@read
def get_exrates(ticker=None, min_date=None, max_date=None): def get_exrates(ticker=None, min_date=None, max_date=None):
sqls = [] sqls = []
if min_date: if min_date:
sqls.append(f"re_date >= '{format_date(min_date)}'") sqls.append(f"re_date >= '{format_date(min_date)}'")
if max_date: if max_date:
sqls.append(f"re_date <= '{format_date(max_date)}'") sqls.append(f"re_date <= '{format_date(max_date)}'")
return get_list(*sqls, re_ticker=ticker) return f'''select {','.join([f"{x[0]} as {x[1]}" for x in __COLUMNS__.items()])} from robo_exrate {where(*sqls, re_ticker=ticker)}'''
@read(one=True)
def get_exrate(ticker, date): def get_exrate(ticker, date):
return get_one(re_ticker=ticker, re_date=date) return f'''select {','.join([f"{x[0]} as {x[1]}" for x in __COLUMNS__.items()])} from robo_exrate {where(re_ticker=ticker, re_date=date)}'''
from framework import read, where, format_date, to_tuple from framework import read, where, format_date, to_tuple
@read __COLUMNS__ = {
def get_list(*args, **kwargs): 'rfn_fund_id': 'fund_id',
return f'''select rfn_fund_id as fund_id, rfn_date as nav_date, rfn_nav_cal as nav_cal from robo_fund_navs {where(*args, **kwargs)}''' 'rfn_date': 'nav_date',
'rfn_nav_cal': 'nav_cal',
}
@read(one=True)
def get_one(*args, **kwargs):
return f'''select rfn_fund_id as fund_id, rfn_date as nav_date, rfn_nav_cal as nav_cal from robo_fund_navs {where(*args, **kwargs)}'''
@read
def get_navs(fund_id=None, min_date=None, max_date=None): def get_navs(fund_id=None, min_date=None, max_date=None):
sqls = [] sqls = []
if min_date: if min_date:
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)}'")
return get_list(*sqls, rfn_fund_id=to_tuple(fund_id)) return f'''select {','.join([f"`{x[0]}` as `{x[1]}`" for x in __COLUMNS__.items()])} from robo_fund_navs {where(*sqls, rfn_fund_id=to_tuple(fund_id))}'''
...@@ -15,6 +15,8 @@ framework: ...@@ -15,6 +15,8 @@ framework:
server: smtphz.qiye.163.com server: smtphz.qiye.163.com
user: jft-ra@thizgroup.com user: jft-ra@thizgroup.com
password: 5dbb#30ec6d3 password: 5dbb#30ec6d3
mulit-process:
max-workers: 4
logger: logger:
version: 1 version: 1
use: ${LOG_NAME:root} use: ${LOG_NAME:root}
...@@ -46,21 +48,33 @@ framework: ...@@ -46,21 +48,33 @@ framework:
root: root:
level: INFO level: INFO
handlers: [console] handlers: [console]
main:
start-date: 2022-09-01
basic: basic:
navs: navs:
exrate: exrate:
- from: EUR - from: EUR
ticker: EURUSD BGN Curncy ticker: EURUSD BGN Curncy
asset_pool: asset-pool:
asset_optimize: asset-optimize:
sortino_weight: sortino-weight:
- months: 3 - months: 3
weight: 0.5 weight: 0.5
- months: 6 - months: 6
weight: 0.2 weight: 0.2
- years: 1 - years: 1
weight: 0.2 weight: 0.2
asset_risk: asset-risk:
rtn_day: 5 advance-months: 3
rtn-day: 5
ewma:
condition-total: 6
condition-meet: 4
factor: 0.3
threshold: 0
cvar:
min-volume: 30
threshold: -0.03
coef: 0.95
from .date_utils import * from .date_utils import *
from .base import * from .base import *
from .database import read, write, transaction, where from .database import read, write, transaction, where, to_columns
from .env_config import config, get_config from .env_config import config, get_config
from .logger import build_logger, _log from .logger import build_logger, logger as log
from .injectable import component, autowired, get_instance, init_injectable as _init_injectable from .injectable import component, autowired, get_instance, init_injectable as _init_injectable
from .mulit_process import process_pool, process
_init_injectable() _init_injectable()
del injectable, logger, env_config, database, base, date_utils, _init_injectable del injectable, logger, env_config, database, base, date_utils, _init_injectable, mulit_process
logger = _log
del _log
...@@ -5,8 +5,8 @@ from enum import Enum ...@@ -5,8 +5,8 @@ from enum import Enum
import pymysql import pymysql
from pymysql.cursors import DictCursor from pymysql.cursors import DictCursor
from .date_utils import format_date, datetime from framework.date_utils import format_date, datetime
from .env_config import get_config from framework.env_config import get_config
class DatabaseError(Exception): class DatabaseError(Exception):
...@@ -141,3 +141,7 @@ def where(*args, **kwargs) -> str: ...@@ -141,3 +141,7 @@ def where(*args, **kwargs) -> str:
if args: if args:
result.extend([x for x in args if x]) result.extend([x for x in args if x])
return f"where {' and '.join(result)}" if result else '' return f"where {' and '.join(result)}" if result else ''
def to_columns(columns: dict, datas: dict) -> dict:
return dict([(x[0], datas[x[1]]) for x in columns.items()])
import calendar import calendar
from datetime import timedelta, datetime from datetime import timedelta, datetime, date
def filter_weekend(day): def filter_weekend(day):
...@@ -27,5 +27,10 @@ def parse_date(date, has_time=False): ...@@ -27,5 +27,10 @@ def parse_date(date, has_time=False):
return datetime.strptime(date, '%Y-%m-%d %H:%M:%S' if has_time else '%Y-%m-%d') return datetime.strptime(date, '%Y-%m-%d %H:%M:%S' if has_time else '%Y-%m-%d')
def get_quarter_start(today=datetime.today()):
result = date(today.year, today.month - (today.month - 1) % 3, 1)
return datetime.combine(result, datetime.min.time())
if __name__ == '__main__': if __name__ == '__main__':
print(parse_date('2022-10-01 10:24:24', has_time=True)) print(get_quarter_start())
...@@ -92,6 +92,6 @@ config = build_config() ...@@ -92,6 +92,6 @@ config = build_config()
def get_config(module: str = None): def get_config(module: str = None):
result = config result = config
if module: if module:
for name in module.split('.'): for name in [x.replace('_', '-') for x in module.split('.')]:
result = result[name] if name in result else {} result = result[name] if name in result else {}
return result return result
...@@ -15,4 +15,4 @@ def build_logger(config, name='root'): ...@@ -15,4 +15,4 @@ def build_logger(config, name='root'):
config = get_config(__name__) config = get_config(__name__)
_log = build_logger(config, name=config['use'] if 'use' in config else None) if config else None logger = build_logger(config, name=config['use'] if 'use' in config else None) if config else None
from concurrent.futures import ProcessPoolExecutor
from framework.env_config import get_config
from functools import partial, wraps
config = get_config(__name__)
process_pool = ProcessPoolExecutor(max_workers=config['max-workers'] or 2)
def process(func=None):
if func is None:
return partial(process)
@wraps(func)
def wrap(*args, **kwargs):
return process_pool.submit(func, *args, **kwargs)
return wrap
from framework import autowired, parse_date, logger from framework import autowired, parse_date, log
from api import AssetOptimize, AssetRisk from api import AssetPool
@autowired @autowired
def start(optimize: AssetOptimize = None, risk: AssetRisk = None): def start(pool: AssetPool = None):
pool = optimize.get_optimize_pool(parse_date('2022-11-07')) day = parse_date('2022-11-07')
logger.info(pool) log.info(pool.get_pool(day))
risk.is_risk(1, parse_date('2022-11-07'))
if __name__ == '__main__': if __name__ == '__main__':
log.info("start")
start() start()
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