Commit 1213b877 authored by wenwen.tang's avatar wenwen.tang 😕

回测平台调整:持有基金自身配息不再下次调仓后拿来再投资

parent 0f0faaa9
......@@ -645,3 +645,12 @@ class RebalanceSignal(ABC):
:param risk: 指定的风险等级
:return: 如果有信号,则返回信号数据,否则返回None
'''
@abstractmethod
def clear(self, min_date=None, risk: PortfoliosRisk = None):
'''
清理指定的数据
:param min_date: 指定的起始时间
:param risk: 指定的风险等级
'''
pass
\ No newline at end of file
......@@ -231,15 +231,15 @@ reports: # 报告模块相关
subject: "SVROBO6-实盘版-每日监测_{today}"
content: "Dear All: 附件是今天生成的监测数据,請驗收,謝謝! 注>:該郵件為自動發送,如有問題請聯繫矽谷團隊 telan_qian@chifufund.com"
robo-executor: # 执行器相关
use: ${ROBO_EXECUTOR:real} # 执行哪个执行器,优先取系统环境变量ROBO_EXECUTOR的值,默认backtest
sync-data: ${SYNC_DATA:on} # 是否开启同步资料数据
use: ${ROBO_EXECUTOR:backtest} # 执行哪个执行器,优先取系统环境变量ROBO_EXECUTOR的值,默认backtest
sync-data: ${SYNC_DATA:off} # 是否开启同步资料数据
backtest: # 回测执行器相关
start-date: 2022-09-30 # 回测起始日期
start-date: 2022-09-22 # 回测起始日期
end-date: 2023-07-03 # 回测截止日期
sealing-period: 10 #调仓封闭期
start-step: ${BACKTEST_START_STEP:3} # 回测从哪一步开始执行 1:计算资产池;2:计算最优投组:3:计算再平衡信号以及持仓投组
end-step: ${BACKTEST_END_STEP:3} # 回测从哪一步执行完成后结束执行 1:计算资产池;2:计算最优投组:3:计算再平衡信号以及持仓投组
clean-up: true
clean-up: off
real: # 实盘执行器
export: ${EXPORT_ENABLE:off} # 是否开启报告
start-date: 2023-05-08 # 实盘开始时间
......
......@@ -237,11 +237,11 @@ class InvTrustPortfoliosHolder(DividendPortfoliosHolder):
fund_div_tuple = self.get_navs_and_div(fund_ids=tuple(set(weight) | set(share)), day=day)
navs = fund_div_tuple[0]
fund_dividend = fund_div_tuple[1]
fund_dividend = sum(
fund_dividend = last_nav['fund_div'] + sum(
map(lambda k: share[k] * fund_dividend[k], filter(lambda k: k in fund_dividend, share.keys())))
dividend_acc = last_nav['div_acc']
fund_av = round(sum([navs[x] * y for x, y in share.items()]), 4) + last_nav['fund_div']
asset_nav = fund_av + fund_dividend
asset_nav = fund_av
nav = last_nav['nav'] * asset_nav / last_nav['asset_nav']
share = {x: fund_av * w / navs[x] for x, w in weight.items()}
if self.is_first_workday(day):
......@@ -313,7 +313,7 @@ class InvTrustPortfoliosHolder(DividendPortfoliosHolder):
weight = format_weight(weight)
fund_dividend = last_nav['fund_div'] + sum(
map(lambda k: share[k] * fund_dividend[k], filter(lambda k: k in fund_dividend, share.keys())))
asset_nav = fund_av + fund_dividend
asset_nav = fund_av
nav = last_nav['nav'] * asset_nav / last_nav['asset_nav']
div_forecast = last_nav['div_forecast']
if self.is_first_workday(day):
......
......@@ -73,6 +73,9 @@ class BaseRebalanceSignal(RebalanceSignal, ABC):
last_re = rrs.get_last_one(max_date=day, risk=risk, effective=True)
return last_re
def clear(self, min_date=None, risk: PortfoliosRisk = None):
rrs.delete(min_date=min_date, risk=risk)
@component(bean_name='signal-report')
class SignalReportor(RoboReportor):
......
......@@ -24,27 +24,27 @@ class BacktestExecutor(RoboExecutor):
@autowired(names={'datum': 'hk-datum'})
def __init__(self, datum: Datum = None, pool: AssetPool = None,
syncs: List[DataSync] = None, export: RoboExportor = None,
builder: PortfoliosBuilder = None, hold: PortfoliosHolder = None):
builder: PortfoliosBuilder = None, hold: PortfoliosHolder = None,
signal: RebalanceSignal = None):
self._datum = datum
self._pool = pool
self._builder = builder
self._hold = hold
self._syncs = syncs
self._export = export
self._signal = signal
self._config = get_config(__name__)['backtest']
@staticmethod
def get_last_business_day(start_date, end_date):
# 生成日期范围并转换为DataFrame
dates = pd.date_range(start_date, end_date, freq='MS')
dates = pd.date_range(start_date, end_date, freq='M')
if dates[0] != start_date:
dates = dates.insert(0, start_date)
df = pd.DataFrame({'dates': dates})
df['last_business_day'] = df['dates'].map(
lambda date: pd.date_range(start=date, periods=1, freq='BM')[-1]
)
# 每隔n个月提取第一个工作日
result = []
for i in range(0, len(df), get_config('portfolios')['holder']['warehouse-frequency']):
result.append(df.iloc[i]['last_business_day'])
result.append(df.iloc[i]['dates'])
delta = workday_range(result[0], result[1])
period = get_config(__name__)['backtest']['sealing-period']
if len(delta) <= period:
......@@ -83,6 +83,7 @@ class BacktestExecutor(RoboExecutor):
BacktestStep.NORMAL_PORTFOLIO):
logger.info('start to clear normal portfolios'.center(50, '-'))
self._builder.clear()
self._signal.clear()
if self.start_step.within(BacktestStep.HOLD_PORTFOLIO) and self.end_step.without(BacktestStep.HOLD_PORTFOLIO):
logger.info('start to clear hold portfolios'.center(50, '-'))
self._hold.clear()
......@@ -199,5 +200,3 @@ class RealExecutor(RoboExecutor):
f'export email for date[{format_date(date)}] send success, use[{(dt.now() - now).seconds}s]')
else:
logger.info(f'today[{format_date(date)}] is a rest day, do not execute the daily real robo.')
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