Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
R
robo-dividend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wenwen.tang
robo-dividend
Commits
938ef10c
Commit
938ef10c
authored
Dec 13, 2022
by
jichao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
回测报告增加基金池
parent
22435898
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
34 additions
and
22 deletions
+34
-22
asset_risk.py
asset_pool/asset_risk.py
+4
-4
test_case.py
asset_pool/test_case.py
+5
-1
config.yml
config.yml
+10
-9
robo_executor.py
robo_executor.py
+15
-8
No files found.
asset_pool/asset_risk.py
View file @
938ef10c
...
...
@@ -89,11 +89,11 @@ class CvarEwmaAssetRisk(AssetRisk):
start_date
=
last_start
[
'date'
]
if
last_start
else
self
.
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
cvar_start_date
=
risk_rtns
.
loc
[
risk_rtns
.
nav
.
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
:
if
row
.
nav
<
rtns
[
rtns
.
date
==
cvar_start_date
]
.
iloc
[
0
]
.
nav
:
# 当日回报率跌破最低点, 则直接触发
tigger
=
True
elif
row
[
'rtn'
]
<=
self
.
_config
[
'cvar'
][
'threshold'
]
and
len
(
cvar_rtns
)
>=
self
.
_config
[
'cvar'
][
'min-volume'
]:
...
...
@@ -136,7 +136,7 @@ class CvarEwmaAssetRisk(AssetRisk):
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
=
fund_navs
[[
'date'
,
'rtn'
]]
fund_navs
.
rename
(
columns
=
{
'nav_date'
:
'date'
,
'nav_cal'
:
'nav'
},
inplace
=
True
)
fund_navs
=
fund_navs
[[
'date'
,
'
nav'
,
'
rtn'
]]
return
fund_navs
.
to_dict
(
'records'
)
return
[]
asset_pool/test_case.py
View file @
938ef10c
...
...
@@ -3,7 +3,7 @@ import unittest
from
py_jftech
import
autowired
,
parse_date
,
to_str
from
api
import
AssetPool
,
RoboReportor
from
api
import
AssetPool
,
RoboReportor
,
AssetRisk
logger
=
logging
.
getLogger
(
__name__
)
...
...
@@ -19,6 +19,10 @@ class AssetPoolTest(unittest.TestCase):
result
=
report
.
load_report
(
max_date
=
parse_date
(
'2009-12-31'
))
logger
.
info
(
to_str
(
result
))
@
autowired
def
test_next_risk_date
(
self
,
risk
:
AssetRisk
=
None
):
risk
.
build_risk_date
(
asset_id
=
46
)
if
__name__
==
'__main__'
:
unittest
.
main
()
config.yml
View file @
938ef10c
...
...
@@ -208,23 +208,24 @@ reports: # 报告模块相关
backtest
:
# 回测导出曹策略
exist-build
:
on
# 如果报告文件存在,是否重新构建文件
save-path
:
${EXPORT_PATH:excels}
# 导出报告文件存放路径,如果以./或者../开头,则会以执行python文件为根目录,如果以/开头,则为系统绝对路径,否则,以项目目录为根目录
file-name
:
${EXPORT_FILENAME:
navs
}
file-name
:
${EXPORT_FILENAME:
asset-pool
}
include-report
:
# 需要导出的报告类型列表,下面的顺序,也代表了excel中sheet的顺序
# - navs-report # 净值报告
-
hold-report
# 持仓报告
-
signal-report
# 信号报告
#
- hold-report # 持仓报告
#
- signal-report # 信号报告
-
asset-pool-report
# 基金池报告
-
benckmark-report
# benckmark报告
-
indicators-report
# 各种特殊指标报告
-
fixed-range-report
# 固定区间收益报告
-
relative-range-report
# 相对区间收益报告
#
- benckmark-report # benckmark报告
#
- indicators-report # 各种特殊指标报告
#
- fixed-range-report # 固定区间收益报告
#
- relative-range-report # 相对区间收益报告
robo-executor
:
# 执行器相关
use
:
${ROBO_EXECUTOR:backtest}
#执行哪个执行器,优先取系统环境变量ROBO_EXECUTOR的值,默认backtest
sync-data
:
${SYNC_DATA:o
n
}
sync-data
:
${SYNC_DATA:o
ff
}
backtest
:
# 回测执行器相关
start-date
:
2008-01-02
# 回测起始日期
end-date
:
2022-11-01
# 回测截止日期
start-step
:
4
# 回测从哪一步开始执行 1:计算资产ewma;2:计算资产池;3:计算最优投组:4:计算再平衡信号以及持仓投组
start-step
:
1
# 回测从哪一步开始执行 1:计算资产ewma;2:计算资产池;3:计算最优投组:4:计算再平衡信号以及持仓投组
end-step
:
2
# 回测从哪一步执行完成后结束执行 1:计算资产ewma;2:计算资产池;3:计算最优投组:4:计算再平衡信号以及持仓投组
clean-up
:
on
real
:
# 实盘执行器
start-date
:
2022-11-01
# 实盘开始时间
...
...
robo_executor.py
View file @
938ef10c
...
...
@@ -30,6 +30,9 @@ class BacktestStep(Enum):
def
within
(
self
,
step
:
Enum
):
return
self
.
value
<=
step
.
value
def
without
(
self
,
step
:
Enum
):
return
self
.
value
>=
step
.
value
@
component
(
bean_name
=
'backtest'
)
class
BacktestExecutor
(
RoboExecutor
):
...
...
@@ -55,6 +58,10 @@ class BacktestExecutor(RoboExecutor):
def
start_step
(
self
)
->
BacktestStep
:
return
BacktestStep
(
self
.
_config
[
'start-step'
])
@
property
def
end_step
(
self
)
->
BacktestStep
:
return
BacktestStep
(
self
.
_config
[
'end-step'
])
if
'end-step'
in
self
.
_config
else
BacktestStep
.
HOLD_PORTFOLIO
@
property
def
is_sync_data
(
self
):
return
get_config
(
__name__
)[
'sync-data'
]
...
...
@@ -68,16 +75,16 @@ class BacktestExecutor(RoboExecutor):
return
self
.
_config
[
'clean-up'
]
if
'clean-up'
in
self
.
_config
else
True
def
clear_datas
(
self
):
if
self
.
start_step
.
within
(
BacktestStep
.
EWMA_VALUE
):
if
self
.
start_step
.
within
(
BacktestStep
.
EWMA_VALUE
)
and
self
.
end_step
.
without
(
BacktestStep
.
EWMA_VALUE
)
:
logger
.
info
(
'start to clear fund ewma value'
.
center
(
50
,
'-'
))
self
.
_risk
.
clear
()
if
self
.
start_step
.
within
(
BacktestStep
.
ASSET_POOL
):
if
self
.
start_step
.
within
(
BacktestStep
.
ASSET_POOL
)
and
self
.
end_step
.
without
(
BacktestStep
.
ASSET_POOL
)
:
logger
.
info
(
'start to clear asset pool'
.
center
(
50
,
'-'
))
self
.
_pool
.
clear
()
if
self
.
start_step
.
within
(
BacktestStep
.
NORMAL_PORTFOLIO
):
if
self
.
start_step
.
within
(
BacktestStep
.
NORMAL_PORTFOLIO
)
and
self
.
end_step
.
without
(
BacktestStep
.
NORMAL_PORTFOLIO
)
:
logger
.
info
(
'start to clear normal portfolios'
.
center
(
50
,
'-'
))
self
.
_builder
.
clear
()
if
self
.
start_step
.
within
(
BacktestStep
.
HOLD_PORTFOLIO
):
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
()
self
.
_rule
.
clear_signal
()
...
...
@@ -88,12 +95,12 @@ class BacktestExecutor(RoboExecutor):
sync
.
do_sync
()
if
self
.
is_clean_up
:
self
.
clear_datas
()
if
self
.
start_step
.
within
(
BacktestStep
.
EWMA_VALUE
):
if
self
.
start_step
.
within
(
BacktestStep
.
EWMA_VALUE
)
and
self
.
end_step
.
without
(
BacktestStep
.
EWMA_VALUE
)
:
logger
.
info
(
"start to build fund ewma value."
.
center
(
50
,
'-'
))
now
=
dt
.
now
()
wait
([
self
.
async_build_risk_date
(
x
[
'id'
])
for
x
in
self
.
_datum
.
get_datums
(
type
=
DatumType
.
FUND
,
risk
=
(
3
,
4
,
5
))])
logger
.
info
(
f
"build fund ewma value success, use[{(dt.now() - now).seconds}s]"
)
if
self
.
start_step
.
within
(
BacktestStep
.
ASSET_POOL
):
if
self
.
start_step
.
within
(
BacktestStep
.
ASSET_POOL
)
and
self
.
end_step
.
without
(
BacktestStep
.
ASSET_POOL
)
:
logger
.
info
(
"start to build asset pool"
.
center
(
50
,
'-'
))
now
=
dt
.
now
()
workdays
=
workday_range
(
self
.
start_date
,
self
.
end_date
)
...
...
@@ -102,12 +109,12 @@ class BacktestExecutor(RoboExecutor):
for
date
in
workdays
:
self
.
_pool
.
get_pool
(
date
)
logger
.
info
(
f
"build asset pool success, use[{(dt.now() - now).seconds}s]"
)
if
self
.
start_step
.
within
(
BacktestStep
.
NORMAL_PORTFOLIO
):
if
self
.
start_step
.
within
(
BacktestStep
.
NORMAL_PORTFOLIO
)
and
self
.
end_step
.
without
(
BacktestStep
.
NORMAL_PORTFOLIO
)
:
logger
.
info
(
"start to build normal portfolios"
.
center
(
50
,
'-'
))
now
=
dt
.
now
()
wait
([
self
.
async_build_portfolios
(
day
,
risk
)
for
risk
in
PortfoliosRisk
for
day
in
workday_range
(
self
.
start_date
,
self
.
end_date
)])
logger
.
info
(
f
"build normal portfolios success, use[{(dt.now() - now).seconds}s]"
)
if
self
.
start_step
.
within
(
BacktestStep
.
HOLD_PORTFOLIO
):
if
self
.
start_step
.
within
(
BacktestStep
.
HOLD_PORTFOLIO
)
and
self
.
end_step
.
without
(
BacktestStep
.
HOLD_PORTFOLIO
)
:
logger
.
info
(
"start to build hold portfolios"
.
center
(
50
,
'-'
))
now
=
dt
.
now
()
wait
([
self
.
async_build_hold
(
x
)
for
x
in
PortfoliosRisk
])
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment