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
80aaec18
Commit
80aaec18
authored
Jan 11, 2023
by
jichao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
调整信号规则逻辑
parent
cab7a25f
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
52 additions
and
32 deletions
+52
-32
api.py
api.py
+4
-2
holder.py
portfolios/holder.py
+2
-2
test_case.py
portfolios/test_case.py
+1
-2
robo_rebalance_signal.py
rebalance/dao/robo_rebalance_signal.py
+5
-0
ruler.py
rebalance/ruler.py
+38
-24
test_case.py
rebalance/test_case.py
+2
-2
No files found.
api.py
View file @
80aaec18
...
@@ -50,6 +50,7 @@ class SolveType(Enum):
...
@@ -50,6 +50,7 @@ class SolveType(Enum):
@
unique
@
unique
class
SignalType
(
Enum
):
class
SignalType
(
Enum
):
NONE
=
-
1
INIT
=
0
INIT
=
0
CRISIS_EXP
=
1
CRISIS_EXP
=
1
CRISIS_ONE
=
2
CRISIS_ONE
=
2
...
@@ -62,7 +63,7 @@ class SignalType(Enum):
...
@@ -62,7 +63,7 @@ class SignalType(Enum):
# 信号处理优先级
# 信号处理优先级
SignalType
.
CRISIS_ONE
.
level
=
1
SignalType
.
CRISIS_ONE
.
level
=
1
SignalType
.
CRISIS_TWO
.
level
=
2
SignalType
.
CRISIS_TWO
.
level
=
1
SignalType
.
MARKET_RIGHT
.
level
=
3
SignalType
.
MARKET_RIGHT
.
level
=
3
SignalType
.
HIGH_BUY
.
level
=
4
SignalType
.
HIGH_BUY
.
level
=
4
SignalType
.
LOW_BUY
.
level
=
5
SignalType
.
LOW_BUY
.
level
=
5
...
@@ -519,11 +520,12 @@ class RebalanceRuler(ABC):
...
@@ -519,11 +520,12 @@ class RebalanceRuler(ABC):
'''
'''
@
abstractmethod
@
abstractmethod
def
take_next_signal
(
self
,
day
,
risk
:
PortfoliosRisk
):
def
take_next_signal
(
self
,
day
,
risk
:
PortfoliosRisk
,
only_today
=
True
):
'''
'''
取出指定日期,指定风险等级的再平衡信号数据,注意取出消费后,无法退回,非幂等函数
取出指定日期,指定风险等级的再平衡信号数据,注意取出消费后,无法退回,非幂等函数
:param day: 指定日期
:param day: 指定日期
:param risk: 指定风险等级
:param risk: 指定风险等级
:param only_today: 只获取今天是否有信号
:return: 如果存在,则返回取出的再平衡信号信息,否则返回None
:return: 如果存在,则返回取出的再平衡信号信息,否则返回None
'''
'''
pass
pass
...
...
portfolios/holder.py
View file @
80aaec18
...
@@ -59,8 +59,8 @@ class NextReblanceHolder(PortfoliosHolder):
...
@@ -59,8 +59,8 @@ class NextReblanceHolder(PortfoliosHolder):
logger
.
info
(
f
"start to build hold portfolio[{risk.name}] for date[{format_date(start)}]"
)
logger
.
info
(
f
"start to build hold portfolio[{risk.name}] for date[{format_date(start)}]"
)
signal
=
None
signal
=
None
if
last_nav
:
if
last_nav
:
last_re
=
rhp
.
get_last_one
(
max_date
=
start
,
risk
=
risk
,
rebalance
=
True
)
last_re
_date
=
self
.
get_last_rebalance_date
(
risk
=
risk
,
max_date
=
start
)
if
len
(
workday_range
(
last_re
[
'date'
]
,
start
))
>
self
.
interval_days
:
if
len
(
workday_range
(
last_re
_date
,
start
))
>
self
.
interval_days
:
signal
=
self
.
_rule
.
take_next_signal
(
prev_workday
(
start
),
risk
)
signal
=
self
.
_rule
.
take_next_signal
(
prev_workday
(
start
),
risk
)
else
:
else
:
signal
=
self
.
_rule
.
take_next_signal
(
prev_workday
(
start
),
risk
)
signal
=
self
.
_rule
.
take_next_signal
(
prev_workday
(
start
),
risk
)
...
...
portfolios/test_case.py
View file @
80aaec18
...
@@ -29,8 +29,7 @@ class PortfoliosTest(unittest.TestCase):
...
@@ -29,8 +29,7 @@ class PortfoliosTest(unittest.TestCase):
@
autowired
(
names
=
{
'hold'
:
'next-re'
})
@
autowired
(
names
=
{
'hold'
:
'next-re'
})
def
test_build_hold
(
self
,
hold
:
PortfoliosHolder
=
None
):
def
test_build_hold
(
self
,
hold
:
PortfoliosHolder
=
None
):
hold
.
build_hold_portfolio
(
parse_date
(
'2016-01-01'
),
PortfoliosRisk
.
FT9
)
hold
.
build_hold_portfolio
(
parse_date
(
'2022-11-01'
),
PortfoliosRisk
.
FT9
)
pass
@
autowired
(
names
=
{
'reportor'
:
'hold-report'
})
@
autowired
(
names
=
{
'reportor'
:
'hold-report'
})
def
test_hold_report
(
self
,
reportor
:
RoboReportor
=
None
):
def
test_hold_report
(
self
,
reportor
:
RoboReportor
=
None
):
...
...
rebalance/dao/robo_rebalance_signal.py
View file @
80aaec18
...
@@ -88,6 +88,11 @@ def update(id, datas):
...
@@ -88,6 +88,11 @@ def update(id, datas):
'''
'''
@
write
def
delete_by_id
(
id
):
return
f
"delete from robo_rebalance_signal where rrs_id = {id}"
@
write
@
write
def
delete
(
min_date
=
None
,
risk
:
PortfoliosRisk
=
None
):
def
delete
(
min_date
=
None
,
risk
:
PortfoliosRisk
=
None
):
if
min_date
is
None
and
risk
is
None
:
if
min_date
is
None
and
risk
is
None
:
...
...
rebalance/ruler.py
View file @
80aaec18
...
@@ -39,35 +39,49 @@ class LevelRebalanceRuler(RebalanceRuler):
...
@@ -39,35 +39,49 @@ class LevelRebalanceRuler(RebalanceRuler):
else
:
else
:
return
{
t
:
result
for
t
in
PortfoliosType
}
return
{
t
:
result
for
t
in
PortfoliosType
}
def
take_next_signal
(
self
,
day
,
risk
:
PortfoliosRisk
):
def
without_disable_period
(
self
,
day
,
risk
:
PortfoliosRisk
)
->
bool
:
last_re
=
rrs
.
get_last_one
(
max_date
=
day
,
risk
=
risk
,
effective
=
True
)
if
SignalType
(
last_re
[
'type'
])
.
p_type
in
self
.
disable_period
:
return
len
(
workday_range
(
last_re
[
'date'
],
day
))
>
self
.
disable_period
[
SignalType
(
last_re
[
'type'
])
.
p_type
]
return
False
def
take_next_signal
(
self
,
day
,
risk
:
PortfoliosRisk
,
only_today
=
True
):
last_re
=
rrs
.
get_last_one
(
max_date
=
day
,
risk
=
risk
,
effective
=
True
)
last_re
=
rrs
.
get_last_one
(
max_date
=
day
,
risk
=
risk
,
effective
=
True
)
if
not
last_re
:
if
not
last_re
:
builder
=
[
x
for
x
in
self
.
_signals
if
x
.
signal_type
is
SignalType
.
INIT
][
0
]
builder
=
[
x
for
x
in
self
.
_signals
if
x
.
signal_type
is
SignalType
.
INIT
][
0
]
return
builder
.
get_signal
(
day
,
risk
)
return
builder
.
get_signal
(
day
,
risk
)
long_signals
=
[
x
for
x
in
self
.
_signals
if
risk_signals
=
[
x
for
x
in
self
.
_signals
if
x
.
signal_type
.
p_type
is
not
PortfoliosType
.
NORMAL
]
x
.
signal_type
.
p_type
is
not
PortfoliosType
.
NORMAL
and
x
.
signal_type
.
level
<
SignalType
(
last_re
[
'type'
])
.
level
]
buy_signals
=
[
x
for
x
in
self
.
_signals
if
x
.
signal_type
.
p_type
is
PortfoliosType
.
NORMAL
]
for
long_signal
in
sorted
(
long_signals
,
key
=
lambda
x
:
x
.
signal_type
.
level
):
workdays
=
workday_range
(
next_workday
(
last_re
[
'date'
]),
day
)
last_signal
=
rrs
.
get_last_one
(
max_date
=
day
,
risk
=
risk
)
if
len
(
workdays
)
<=
self
.
_hold
.
interval_days
:
start
=
next_workday
(
last_signal
[
'date'
])
for
date
in
workdays
:
signal
=
long_signal
.
get_signal
(
date
,
risk
)
while
start
<=
day
:
if
signal
:
# 检查风控信号
return
signal
signals
=
{
x
.
signal_type
:
x
.
get_signal
(
start
,
risk
)
for
x
in
risk_signals
if
x
.
signal_type
.
level
<=
SignalType
(
last_re
[
'type'
])
.
level
}
else
:
signals
=
{
x
[
0
]:
x
[
1
]
for
x
in
signals
.
items
()
if
x
[
1
]
is
not
None
}
signal
=
long_signal
.
get_signal
(
day
,
risk
)
# 上次实际调仓类型为危机信号,本次危机信号不调仓
if
signal
:
if
signals
and
SignalType
(
last_re
[
'type'
])
in
[
SignalType
.
CRISIS_ONE
,
SignalType
.
CRISIS_TWO
]:
return
signal
signals
=
{
x
[
0
]:
x
[
1
]
for
x
in
signals
.
items
()
if
x
[
0
]
not
in
[
SignalType
.
CRISIS_ONE
,
SignalType
.
CRISIS_TWO
]}
if
SignalType
(
last_re
[
'type'
])
.
p_type
in
self
.
disable_period
:
# 检查买入信号,只有当天需要检查
re_date
=
self
.
_hold
.
get_last_rebalance_date
(
risk
=
risk
,
max_date
=
day
)
if
not
signals
and
start
==
day
and
self
.
without_disable_period
(
day
,
risk
):
if
re_date
:
signals
=
{
x
.
signal_type
:
x
.
get_signal
(
start
,
risk
)
for
x
in
buy_signals
}
workdays
=
workday_range
(
re_date
,
day
)
signals
=
{
x
[
0
]:
x
[
1
]
for
x
in
signals
.
items
()
if
x
[
1
]
is
not
None
}
if
len
(
workdays
)
<
self
.
disable_period
[
SignalType
(
last_re
[
'type'
])
.
p_type
]:
if
signals
:
return
None
if
SignalType
(
last_signal
[
'type'
])
is
SignalType
.
NONE
:
for
temp_signal
in
sorted
([
x
for
x
in
self
.
_signals
if
x
.
signal_type
.
p_type
is
PortfoliosType
.
NORMAL
],
key
=
lambda
x
:
x
.
signal_type
.
level
):
rrs
.
delete_by_id
(
last_signal
[
'id'
])
signal
=
temp_signal
.
get_signal
(
day
,
risk
)
return
signals
[
sorted
(
signals
.
keys
(),
key
=
lambda
x
:
x
.
level
)[
0
]]
if
signal
:
start
=
next_workday
(
start
)
return
signal
if
SignalType
(
last_signal
[
'type'
])
is
SignalType
.
NONE
:
rrs
.
update
(
last_signal
[
'id'
],
{
'date'
:
day
})
else
:
rrs
.
insert
({
'date'
:
day
,
'type'
:
SignalType
.
NONE
,
'risk'
:
risk
})
return
None
return
None
def
get_signal_type
(
self
,
sign_id
)
->
SignalType
|
Dict
[
int
,
SignalType
]:
def
get_signal_type
(
self
,
sign_id
)
->
SignalType
|
Dict
[
int
,
SignalType
]:
...
...
rebalance/test_case.py
View file @
80aaec18
...
@@ -23,7 +23,7 @@ class RebalanceTest(unittest.TestCase):
...
@@ -23,7 +23,7 @@ class RebalanceTest(unittest.TestCase):
@
autowired
(
names
=
{
'builder'
:
'crisis_two'
})
@
autowired
(
names
=
{
'builder'
:
'crisis_two'
})
def
test_crisis_two
(
self
,
builder
:
RebalanceSignal
=
None
):
def
test_crisis_two
(
self
,
builder
:
RebalanceSignal
=
None
):
start
=
parse_date
(
'20
08-01-22
'
)
start
=
parse_date
(
'20
20-04-29
'
)
end
=
start
+
relativedelta
(
years
=
3
)
end
=
start
+
relativedelta
(
years
=
3
)
while
start
<
end
:
while
start
<
end
:
signal
=
builder
.
is_trigger
(
start
,
PortfoliosRisk
.
FT9
)
signal
=
builder
.
is_trigger
(
start
,
PortfoliosRisk
.
FT9
)
...
@@ -47,7 +47,7 @@ class RebalanceTest(unittest.TestCase):
...
@@ -47,7 +47,7 @@ class RebalanceTest(unittest.TestCase):
@
autowired
@
autowired
def
test_rebalance_builder
(
self
,
builder
:
RebalanceRuler
=
None
):
def
test_rebalance_builder
(
self
,
builder
:
RebalanceRuler
=
None
):
builder
.
take_next_signal
(
parse_date
(
'202
2-09-01'
),
PortfoliosRisk
.
FT3
)
builder
.
take_next_signal
(
parse_date
(
'202
0-04-29'
),
PortfoliosRisk
.
FT9
)
@
autowired
(
names
=
{
'reportor'
:
'signal-report'
})
@
autowired
(
names
=
{
'reportor'
:
'signal-report'
})
def
test_signal_report
(
self
,
reportor
:
RoboReportor
=
None
):
def
test_signal_report
(
self
,
reportor
:
RoboReportor
=
None
):
...
...
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