Commit 0f7bec38 authored by wenwen.tang's avatar wenwen.tang 😕
parent 1eff3e20
......@@ -2,6 +2,7 @@ import json
from abc import ABC, abstractmethod
from sys import exception
import numpy as np
import pandas as pd
from dateutil.relativedelta import relativedelta
from empyrical import sortino_ratio, annual_volatility
......@@ -117,14 +118,15 @@ class FundDividendSortinoAssetOptimize(SortinoAssetOptimize):
sortino = sortino.T
sortino['score'] = sortino.apply(lambda r: sum([x['weight'] * r[x['name']] for x in self._config]), axis=1)
sortino.sort_values('score', ascending=False, inplace=True)
records = sortino.to_dict(orient='records')
data = {key: record for record in records for key in fund_ids}
records = sortino.to_dict(orient='index')
data = {fund_ids[k]: v for k, v in records.items()}
self.save_sortino(day, data)
# 取得分数高的前optimize_count个
return pct_change.columns[sortino.index[0:self.optimize_count]].values, sortino['score']
def save_sortino(self, day, datas):
for key, record in datas.items():
record = {k: v for k, v in record.items() if not (np.isnan(v) or np.isinf(v))}
robo_indicator.update_sortino(key, day, json.dumps(record))
def get_optimize_pool(self, day):
......@@ -143,6 +145,8 @@ class FundDividendSortinoAssetOptimize(SortinoAssetOptimize):
pool.extend(self.find_optimize(tuple(fund_group), day)[0])
elif len(fund_group) <= self.optimize_count:
pool.extend(fund_group)
if len(pool) < get_config('portfolios.solver.asset-count')[0]:
raise ValueError(f"基金优选个数小于{get_config('portfolios.solver.asset-count')[0]},请调整参数")
rop.insert(day, AssetPoolType.OPTIMIZE, sorted(pool))
last_one = rop.get_last_one(day=day, type=AssetPoolType.OPTIMIZE)
return json.loads(last_one['asset_ids'])
......@@ -156,10 +160,12 @@ class FundDividendSortinoAssetOptimize(SortinoAssetOptimize):
fund_ids = [fund['id'] for fund in funds]
pct_change = pd.DataFrame(self.get_pct_change(fund_ids, day))
pct_change.set_index('date', inplace=True)
ratio = annual_volatility(
pct_change.truncate(before=(day - relativedelta(**self.annual_volatility_section[0]))))
pct_change = pct_change.truncate(before=(day - relativedelta(**self.annual_volatility_section[0])))
# 时间未够计算年化波动的直接剔除
funds = [fund for fund in funds if fund['id'] in pct_change.columns]
ratio = annual_volatility(pct_change)
ratio = pd.Series(ratio).to_dict()
annual = {fund_id: value for fund_id in fund_ids for value in ratio.values()}
annual = dict(zip(pct_change.columns, ratio.values()))
self.save_annual(day, annual)
filters = self.annual_volatility_filter
for f in filters:
......@@ -167,12 +173,14 @@ class FundDividendSortinoAssetOptimize(SortinoAssetOptimize):
exclude = f.get('exclude')
volatility = f.get('volatility')
records = [fund for fund in funds if fund['customType'] == customType and fund['id'] in annual.keys()]
if exclude:
if exclude is not None:
exclude = exclude if len(records) > exclude else len(records)
records = records[0:-exclude]
if volatility:
records = [record for record in records if annual.get(record['id']) > volatility]
filtered.extend(records)
filtered.extend(records[-exclude:])
if volatility is not None:
records = [record for record in records[0:exclude] if annual.get(record['id']) > volatility]
filtered.extend(records)
for f in filtered:
funds.remove(f)
return funds
def save_annual(self, day, annual):
......@@ -230,6 +238,7 @@ class FundDividendSortinoAssetOptimize(SortinoAssetOptimize):
fund_navs.sort_values('nav_date', inplace=True)
fund_navs = fund_navs.pivot_table(index='nav_date', columns='fund_id', values='nav_cal')
fund_navs.fillna(method='ffill', inplace=True)
fund_navs.dropna(axis=1, inplace=True)
result = round(fund_navs.pct_change().dropna(), 4)
result.reset_index(inplace=True)
result.rename(columns={'nav_date': 'date'}, inplace=True)
......
......@@ -80,11 +80,14 @@ asset-pool: # 资产池模块
optimize-count: 3 #基金优选个数
annual-volatility-filter: #1各资产年化波动率末exclude位 2各资产年化波动率大于volatility
- customType: 1
exclude: 2
volatility: 0
- customType: 2
exclude: 1
volatility: 0
- customType: 2
exclude: 3
volatility: 0.05
- customType: 3
exclude: 2
volatility: 0.001
annual-volatility-section: # 波动率时间区间
- years: 3
portfolios: # 投组模块
......@@ -249,7 +252,7 @@ robo-executor: # 执行器相关
use: ${ROBO_EXECUTOR:backtest} # 执行哪个执行器,优先取系统环境变量ROBO_EXECUTOR的值,默认backtest
sync-data: ${SYNC_DATA:off} # 是否开启同步资料数据
backtest: # 回测执行器相关
start-date: 2023-01-02 # 回测起始日期
start-date: 2013-01-02 # 回测起始日期
end-date: 2023-10-31 # 回测截止日期
sealing-period: 10 #调仓封闭期
start-step: ${BACKTEST_START_STEP:1} # 回测从哪一步开始执行 1:计算资产池;2:计算最优投组:3:计算再平衡信号以及持仓投组
......
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