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
34e8471f
Commit
34e8471f
authored
Jul 10, 2023
by
wenwen.tang
😕
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
实盘
parent
88204c62
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
132 additions
and
18 deletions
+132
-18
config-svrobo5.yml
config-svrobo5.yml
+1
-0
config-svrobo6.yml
config-svrobo6.yml
+14
-12
builder.py
portfolios/builder.py
+78
-2
robo_executor.py
robo_executor.py
+39
-4
No files found.
config-svrobo5.yml
View file @
34e8471f
...
...
@@ -60,6 +60,7 @@ basic: # 基础信息模块
-
'
TEMUSGI
LX
Equity'
real
:
-
'
FGFSACU
LX
Equity'
-
'
TEMUSGI
LX
Equity'
# navs: # 净值模块
# exrate: # 汇率,如果不开启,整个这块注释掉
# - from: EUR # 需要转换的货币类型
...
...
config-svrobo6.yml
View file @
34e8471f
...
...
@@ -42,10 +42,10 @@ py-jftech:
hold-report
:
portfolios.holder.DivHoldReportor
mpt
:
portfolios.builder.PoemPortfoliosBuilder
dividend-holder
:
portfolios.holder.InvTrustPortfoliosHolder
#
email:
#
server: smtphz.qiye.163.com
#
user: jft-ra@thizgroup.com
#
password: 5dbb#30ec6d3
email
:
server
:
smtphz.qiye.163.com
user
:
jft-ra@thizgroup.com
password
:
5dbb#30ec6d3
mulit-process
:
max-workers
:
${MAX_PROCESS:4}
basic
:
# 基础信息模块
...
...
@@ -60,6 +60,7 @@ basic: # 基础信息模块
-
'
TEMUSGI
LX
Equity'
real
:
-
'
FGFSACU
LX
Equity'
-
'
TEMUSGI
LX
Equity'
# navs: # 净值模块
# exrate: # 汇率,如果不开启,整个这块注释掉
# - from: EUR # 需要转换的货币类型
...
...
@@ -183,7 +184,7 @@ reports: # 报告模块相关
-
month-div-rate-report
# 月度配息率比较
-
year-div-rate-report
# 年度配息率比较
real-daily
:
file-name
:
svROBO
5
_portfolios
file-name
:
svROBO
6
_portfolios
include-report
:
-
daily-hold-report
-
daily-signal-report
...
...
@@ -192,13 +193,13 @@ reports: # 报告模块相关
-
wenwen.tang@thizgroup.com
copies
:
${DAILY_EMAIL_COPIES}
subject
:
default
:
"
ROBO
5
_TAIBEI-实盘版-每日投組推薦_{today}"
rebalance
:
"
ROBO
5
_TAIBEI-实盘版-每日投組推薦_{today}_今日有調倉信號!!!"
default
:
"
ROBO
6
_TAIBEI-实盘版-每日投組推薦_{today}"
rebalance
:
"
ROBO
6
_TAIBEI-实盘版-每日投組推薦_{today}_今日有調倉信號!!!"
content
:
default
:
"
Dear
All:
附件是今天生成的推薦組合,請驗收,謝謝!
注>:該郵件為自動發送,如有問題請聯繫矽谷團隊
telan_qian@chifufund.com"
rebalance
:
"
Dear
All:
附件是今天生成的推薦組合以及調倉信號,請驗收,謝謝!
注>:該郵件為自動發送,如有問題請聯繫矽谷團隊
telan_qian@chifufund.com"
daily-monitor
:
file-name
:
svROBO
5
_monitor
file-name
:
svROBO
6
_monitor
include-report
:
-
name
:
relative-range-report
# 相对区间收益报告
min-date
:
~
...
...
@@ -226,11 +227,11 @@ reports: # 报告模块相关
receives
:
-
wenwen.tang@thizgroup.com
copies
:
${MONITOR_EMAIL_COPIES}
subject
:
"
SVROBO
5
-实盘版-每日监测_{today}"
subject
:
"
SVROBO
6
-实盘版-每日监测_{today}"
content
:
"
Dear
All:
附件是今天生成的监测数据,請驗收,謝謝!
注>:該郵件為自動發送,如有問題請聯繫矽谷團隊
telan_qian@chifufund.com"
robo-executor
:
# 执行器相关
use
:
${ROBO_EXECUTOR:
backtest
}
# 执行哪个执行器,优先取系统环境变量ROBO_EXECUTOR的值,默认backtest
sync-data
:
${SYNC_DATA:o
ff
}
# 是否开启同步资料数据
use
:
${ROBO_EXECUTOR:
real
}
# 执行哪个执行器,优先取系统环境变量ROBO_EXECUTOR的值,默认backtest
sync-data
:
${SYNC_DATA:o
n
}
# 是否开启同步资料数据
backtest
:
# 回测执行器相关
start-date
:
2022-09-30
# 回测起始日期
end-date
:
2023-03-01
# 回测截止日期
...
...
@@ -239,7 +240,8 @@ robo-executor: # 执行器相关
end-step
:
${BACKTEST_END_STEP:3}
# 回测从哪一步执行完成后结束执行 1:计算资产池;2:计算最优投组:3:计算再平衡信号以及持仓投组
clean-up
:
true
real
:
# 实盘执行器
start-date
:
2022-09-01
# 实盘开始时间
export
:
${EXPORT_ENABLE:on}
# 是否开启报告
start-date
:
2023-01-01
# 实盘开始时间
...
...
portfolios/builder.py
View file @
34e8471f
import
json
import
logging
from
datetime
import
datetime
as
dt
from
datetime
import
datetime
as
dt
,
timedelta
from
typing
import
List
from
py_jftech
import
component
,
autowired
,
format_date
import
pandas
as
pd
from
py_jftech
import
component
,
autowired
,
format_date
,
prev_workday
,
is_workday
from
pymysql
import
IntegrityError
,
constants
from
api
import
PortfoliosBuilder
,
PortfoliosRisk
,
AssetPool
,
Navs
,
PortfoliosType
,
Datum
,
SolveType
,
SolverFactory
,
\
...
...
@@ -143,3 +144,78 @@ class SignalReportor(RoboReportor):
'weight'
:
weight
})
return
result
@
component
(
bean_name
=
'daily-hold-report'
)
class
DailyHoldReportor
(
RoboReportor
):
@
autowired
def
__init__
(
self
,
datum
:
Datum
=
None
):
self
.
_datum
=
datum
@
property
def
report_name
(
self
)
->
str
:
return
'每日持仓信息'
def
load_report
(
self
,
max_date
=
prev_workday
(
dt
.
today
()),
min_date
=
None
)
->
List
[
dict
]:
# 月初调仓,实际相当于调仓信号在上月月末
first_day
=
max_date
.
replace
(
day
=
1
)
prev_month
=
first_day
-
timedelta
(
days
=
1
)
prev_month
.
replace
(
day
=
prev_month
.
day
)
prev_month
=
prev_month
if
is_workday
(
prev_month
)
else
prev_workday
(
prev_month
)
portfolio
=
rmp
.
get_one
(
prev_month
,
type
=
PortfoliosType
.
NORMAL
,
risk
=
PortfoliosRisk
.
FT3
)
result
=
{}
if
portfolio
:
datum_ids
=
list
(
json
.
loads
(
portfolio
[
'portfolio'
])
.
keys
())
datums
=
pd
.
DataFrame
(
self
.
_datum
.
get_datums
(
type
=
DatumType
.
FUND
,
datum_ids
=
datum_ids
))
datums
.
set_index
(
'id'
,
inplace
=
True
)
result
[
'risk'
]
=
[
portfolio
[
'risk'
]
for
i
in
datum_ids
]
result
[
'rebalance_type'
]
=
[
portfolio
[
'type'
]
for
i
in
datum_ids
]
result
[
'weight'
]
=
[
format
(
i
,
'.0
%
'
)
for
i
in
json
.
loads
(
portfolio
[
'portfolio'
])
.
values
()]
result
[
'asset_ids'
]
=
datum_ids
result
[
'name'
]
=
[
datums
.
loc
[
int
(
i
)][
'chineseName'
]
for
i
in
datum_ids
]
result
[
'lipper_id'
]
=
[
datums
.
loc
[
int
(
i
)][
'lipperKey'
]
for
i
in
datum_ids
]
result
[
'date'
]
=
[
max_date
for
i
in
datum_ids
]
result
[
'rebalance_date'
]
=
[
portfolio
[
'date'
]
for
i
in
datum_ids
]
result
=
pd
.
DataFrame
(
result
)
result
=
result
[
[
'lipper_id'
,
'asset_ids'
,
'name'
,
'weight'
,
'risk'
,
'date'
,
'rebalance_type'
,
'rebalance_date'
]]
return
result
.
to_dict
(
'records'
)
return
[]
@
component
(
bean_name
=
'daily-signal-report'
)
class
DailySignalReportor
(
RoboReportor
):
@
autowired
def
__init__
(
self
,
datum
:
Datum
=
None
):
self
.
_datum
=
datum
@
property
def
report_name
(
self
)
->
str
:
return
'每日调仓信号'
def
load_report
(
self
,
max_date
=
prev_workday
(
dt
.
today
()),
min_date
=
None
)
->
List
[
dict
]:
portfolio
=
rmp
.
get_one
(
max_date
,
type
=
PortfoliosType
.
NORMAL
,
risk
=
PortfoliosRisk
.
FT3
)
result
=
{}
if
portfolio
:
datum_ids
=
list
(
json
.
loads
(
portfolio
[
'portfolio'
])
.
keys
())
datums
=
pd
.
DataFrame
(
self
.
_datum
.
get_datums
(
type
=
DatumType
.
FUND
,
datum_ids
=
datum_ids
))
datums
.
set_index
(
'id'
,
inplace
=
True
)
result
[
'risk'
]
=
[
portfolio
[
'risk'
]
for
i
in
datum_ids
]
result
[
'rebalance_type'
]
=
[
portfolio
[
'type'
]
for
i
in
datum_ids
]
result
[
'weight'
]
=
[
format
(
i
,
'.0
%
'
)
for
i
in
json
.
loads
(
portfolio
[
'portfolio'
])
.
values
()]
result
[
'asset_ids'
]
=
datum_ids
result
[
'name'
]
=
[
datums
.
loc
[
int
(
i
)][
'chineseName'
]
for
i
in
datum_ids
]
result
[
'lipper_id'
]
=
[
datums
.
loc
[
int
(
i
)][
'lipperKey'
]
for
i
in
datum_ids
]
result
[
'date'
]
=
[
max_date
for
i
in
datum_ids
]
result
=
pd
.
DataFrame
(
result
)
result
=
result
[[
'lipper_id'
,
'asset_ids'
,
'name'
,
'weight'
,
'risk'
,
'date'
,
'rebalance_type'
]]
return
result
.
to_dict
(
'records'
)
return
[]
robo_executor.py
View file @
34e8471f
import
logging
import
sys
from
concurrent.futures
import
wait
from
datetime
import
datetime
as
dt
from
datetime
import
datetime
as
dt
,
timedelta
from
typing
import
List
import
pandas
as
pd
from
py_jftech
import
(
component
,
autowired
,
get_config
,
filter_weekend
,
asynchronized
,
parse_date
,
workday_range
parse_date
,
workday_range
,
is_workday
,
prev_workday
,
format_date
)
from
api
import
(
...
...
@@ -135,12 +135,15 @@ class BacktestExecutor(RoboExecutor):
@
component
(
bean_name
=
'real'
)
class
RealExecutor
(
RoboExecutor
):
@
autowired
@
autowired
(
names
=
{
'daily_export'
:
'daily-real-export'
,
'monitor_export'
:
'daily-monitor-export'
})
def
__init__
(
self
,
builder
:
PortfoliosBuilder
=
None
,
hold
:
PortfoliosHolder
=
None
,
syncs
:
List
[
DataSync
]
=
None
,
):
daily_export
:
RoboExportor
=
None
,
monitor_export
:
RoboExportor
=
None
,
pool
:
AssetPool
=
None
,
):
self
.
_builder
=
builder
self
.
_pool
=
pool
self
.
_hold
=
hold
self
.
_syncs
=
syncs
self
.
_daily_export
=
daily_export
self
.
_monitor_export
=
monitor_export
self
.
_config
=
get_config
(
__name__
)[
'real'
]
@
property
...
...
@@ -164,7 +167,39 @@ class RealExecutor(RoboExecutor):
def
include_date
(
self
):
return
[
dt
.
combine
(
x
,
dt
.
min
.
time
())
for
x
in
self
.
_config
[
'include-date'
]]
@
property
def
export
(
self
):
return
self
.
_config
[
'export'
]
if
'export'
in
self
.
_config
else
False
def
start_exec
(
self
):
if
self
.
is_sync_data
:
for
sync
in
self
.
_syncs
:
sync
.
do_sync
()
date
=
self
.
curt_date
if
is_workday
(
date
)
or
date
in
self
.
include_date
:
date
=
prev_workday
(
filter_weekend
(
date
))
for
risk
in
PortfoliosRisk
:
logger
.
info
(
f
"start to build risk[{risk.name}] real for date[{format_date(date)}]"
.
center
(
50
,
'-'
))
now
=
dt
.
now
()
first_day
=
date
.
replace
(
day
=
1
)
prev_month
=
first_day
-
timedelta
(
days
=
1
)
prev_month
.
replace
(
day
=
prev_month
.
day
)
prev_month
=
prev_month
if
is_workday
(
prev_month
)
else
prev_workday
(
prev_month
)
self
.
_pool
.
get_pool
(
prev_month
)
self
.
_builder
.
get_portfolios
(
prev_month
,
risk
)
next_month
=
date
.
replace
(
day
=
28
)
+
timedelta
(
days
=
4
)
prev_month
=
next_month
.
replace
(
day
=
1
)
-
timedelta
(
days
=
1
)
prev_month
=
prev_month
if
is_workday
(
prev_month
)
else
prev_workday
(
prev_month
)
if
date
.
day
==
prev_month
.
day
:
self
.
_pool
.
get_pool
(
date
)
self
.
_builder
.
get_portfolios
(
date
,
risk
)
logger
.
info
(
f
"build risk[{risk.name}] real for date[{format_date(date)}] success, use[{(dt.now() - now).seconds}s]"
)
if
self
.
export
:
now
=
dt
.
now
()
# 每日实盘报告
self
.
_daily_export
.
export
(
max_date
=
date
)
logger
.
info
(
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.'
)
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