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
bf40eee2
Commit
bf40eee2
authored
Nov 25, 2022
by
纪超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加信号模块
parent
4fa60d2f
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
89 additions
and
30 deletions
+89
-30
api.py
api.py
+15
-6
config.yml
config.yml
+2
-1
holder.py
portfolios/holder.py
+2
-2
base_signal.py
rebalance/base_signal.py
+2
-2
ruler.py
rebalance/ruler.py
+49
-0
crisis_signal.py
rebalance/signals/crisis_signal.py
+4
-4
curve_drift.py
rebalance/signals/curve_drift.py
+2
-2
high_low_buy.py
rebalance/signals/high_low_buy.py
+2
-2
init_signal.py
rebalance/signals/init_signal.py
+2
-2
right_side.py
rebalance/signals/right_side.py
+2
-2
test_case.py
rebalance/test_case.py
+7
-7
No files found.
api.py
View file @
bf40eee2
...
@@ -367,7 +367,7 @@ class DriftSolver(ABC):
...
@@ -367,7 +367,7 @@ class DriftSolver(ABC):
pass
pass
class
SignalBuilder
(
ABC
):
class
RebalanceSignal
(
ABC
):
'''
'''
控制信号,发起是否调仓服务
控制信号,发起是否调仓服务
'''
'''
...
@@ -386,17 +386,26 @@ class SignalBuilder(ABC):
...
@@ -386,17 +386,26 @@ class SignalBuilder(ABC):
pass
pass
class
Rebalance
Build
er
(
ABC
):
class
Rebalance
Rul
er
(
ABC
):
'''
'''
再平衡
构建器
再平衡
信号分配器,根据既定的规则,再众多信号中,选出进行再平衡的信号
'''
'''
@
abstractmethod
@
abstractmethod
def
get_rebalance
(
self
,
day
,
risk
:
PortfoliosRisk
):
def
take_next_signal
(
self
,
day
,
risk
:
PortfoliosRisk
):
'''
'''
获取指定日期,指定风险等级的再平衡数据
取出指定日期,指定风险等级的再平衡信号数据,注意取出消费后,无法退回,非幂等函数
:param day: 指定日期
:param day: 指定日期
:param risk: 指定风险等级
:param risk: 指定风险等级
:return: 再平衡数据
:return: 如果存在,则返回取出的再平衡信号信息,否则返回None
'''
pass
@
abstractmethod
def
cancel_signal
(
self
,
sign_id
):
'''
取消信号ID为已消费状态,即设置信号为未消费状态
:param sign_id: 信号ID
:return 取消成功则返回True, 否则返回False
'''
'''
pass
pass
config.yml
View file @
bf40eee2
...
@@ -76,6 +76,7 @@ asset-pool:
...
@@ -76,6 +76,7 @@ asset-pool:
portfolios
:
portfolios
:
holder
:
holder
:
init-nav
:
100
init-nav
:
100
min-interval-days
:
10
solver
:
solver
:
tol
:
1E-10
tol
:
1E-10
navs
:
navs
:
...
@@ -119,7 +120,7 @@ rebalance:
...
@@ -119,7 +120,7 @@ rebalance:
init-factor
:
0.000000002
init-factor
:
0.000000002
high-weight
:
high-weight
:
coef
:
0.2
coef
:
0.2
build
er
:
rul
er
:
disable-period
:
#自然日
disable-period
:
#自然日
normal
:
10
normal
:
10
crisis_1
:
15
crisis_1
:
15
...
...
portfolios/holder.py
View file @
bf40eee2
from
framework
import
component
,
autowired
from
framework
import
component
,
autowired
from
api
import
PortfoliosHolder
,
PortfoliosRisk
,
Rebalance
Build
er
from
api
import
PortfoliosHolder
,
PortfoliosRisk
,
Rebalance
Rul
er
from
portfolios.dao
import
robo_hold_portfolios
as
rhp
from
portfolios.dao
import
robo_hold_portfolios
as
rhp
import
json
import
json
...
@@ -8,7 +8,7 @@ import json
...
@@ -8,7 +8,7 @@ import json
class
NextReblanceHolder
(
PortfoliosHolder
):
class
NextReblanceHolder
(
PortfoliosHolder
):
@
autowired
@
autowired
def
__init__
(
self
,
rebalance
:
Rebalance
Build
er
):
def
__init__
(
self
,
rebalance
:
Rebalance
Rul
er
):
self
.
_rebalance
=
rebalance
self
.
_rebalance
=
rebalance
def
get_portfolios_weight
(
self
,
day
,
risk
:
PortfoliosRisk
):
def
get_portfolios_weight
(
self
,
day
,
risk
:
PortfoliosRisk
):
...
...
rebalance/base_signal.py
View file @
bf40eee2
from
abc
import
ABC
,
abstractmethod
from
abc
import
ABC
,
abstractmethod
from
api
import
SignalBuilder
,
PortfoliosBuilder
,
PortfoliosRisk
from
api
import
RebalanceSignal
,
PortfoliosBuilder
,
PortfoliosRisk
from
framework
import
autowired
from
framework
import
autowired
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
class
Base
SignalBuilder
(
SignalBuilder
,
ABC
):
class
Base
RebalanceSignal
(
RebalanceSignal
,
ABC
):
@
autowired
@
autowired
def
__init__
(
self
,
builder
:
PortfoliosBuilder
=
None
):
def
__init__
(
self
,
builder
:
PortfoliosBuilder
=
None
):
...
...
rebalance/
build
er.py
→
rebalance/
rul
er.py
View file @
bf40eee2
from
framework
import
component
,
autowired
,
get_config
from
framework
import
component
,
autowired
,
get_config
from
api
import
Rebalance
Builder
,
PortfoliosRisk
,
SignalBuilder
,
SignalType
,
PortfoliosType
from
api
import
Rebalance
Ruler
,
PortfoliosRisk
,
RebalanceSignal
,
SignalType
,
PortfoliosType
from
typing
import
List
from
typing
import
List
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
@
component
@
component
class
LevelRebalanceBuilder
(
RebalanceBuilder
):
class
LevelRebalanceRuler
(
RebalanceRuler
):
'''
定义:
1.定义所有调仓类型为非NORMAL类型的信号为清仓信号
2.定义所有调仓类型为NORMAL类型的信号为加仓信号
3.定义持久信号为上次选用调仓的信号时间到当前时间内,该信号都有效
4.定义临时信号为仅当天有效
规则:
1.所有清仓信号为持久信号,所有加仓信号为临时信号
2.对于持久信号规则如下:
2.1 上一次选用信号到当前时间内,是否有持久信号
2.2 如果有,则看级别是否高于上一次选用信号
2.3 如果高于,则输出该信号
3.如果没有持久信号,则从临时信号中根据级别排序找出第一个,作为输出信号
'''
@
autowired
@
autowired
def
__init__
(
self
,
signals
:
List
[
SignalBuilder
]
=
None
):
def
__init__
(
self
,
signals
:
List
[
RebalanceSignal
]
=
None
):
self
.
_signals
=
signals
self
.
_signals
=
signals
self
.
_config
=
get_config
(
__name__
)
self
.
_config
=
get_config
(
__name__
)
...
@@ -17,7 +31,7 @@ class LevelRebalanceBuilder(RebalanceBuilder):
...
@@ -17,7 +31,7 @@ class LevelRebalanceBuilder(RebalanceBuilder):
result
=
self
.
_config
[
'disable-period'
]
result
=
self
.
_config
[
'disable-period'
]
return
{
PortfoliosType
(
x
[
0
]):
x
[
1
]
for
x
in
result
.
items
()}
return
{
PortfoliosType
(
x
[
0
]):
x
[
1
]
for
x
in
result
.
items
()}
def
get_rebalance
(
self
,
day
,
risk
:
PortfoliosRisk
):
def
take_next_signal
(
self
,
day
,
risk
:
PortfoliosRisk
):
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
last_re
and
last_re
[
'date'
]
==
day
:
if
last_re
and
last_re
[
'date'
]
==
day
:
return
last_re
return
last_re
...
@@ -31,4 +45,5 @@ class LevelRebalanceBuilder(RebalanceBuilder):
...
@@ -31,4 +45,5 @@ class LevelRebalanceBuilder(RebalanceBuilder):
return
use_signal
return
use_signal
return
None
return
None
def
cancel_signal
(
self
,
sign_id
):
pass
rebalance/signals/crisis_signal.py
View file @
bf40eee2
...
@@ -5,11 +5,11 @@ from dateutil.relativedelta import relativedelta
...
@@ -5,11 +5,11 @@ from dateutil.relativedelta import relativedelta
from
api
import
PortfoliosRisk
,
SignalType
,
Navs
from
api
import
PortfoliosRisk
,
SignalType
,
Navs
from
framework
import
get_config
,
autowired
,
component
from
framework
import
get_config
,
autowired
,
component
from
rebalance.base_signal
import
Base
SignalBuilder
from
rebalance.base_signal
import
Base
RebalanceSignal
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
class
CrisisSignal
(
Base
SignalBuilder
,
ABC
):
class
CrisisSignal
(
Base
RebalanceSignal
,
ABC
):
@
autowired
@
autowired
def
__init__
(
self
,
navs
:
Navs
=
None
):
def
__init__
(
self
,
navs
:
Navs
=
None
):
...
@@ -58,7 +58,7 @@ class CrisisSignal(BaseSignalBuilder, ABC):
...
@@ -58,7 +58,7 @@ class CrisisSignal(BaseSignalBuilder, ABC):
@
component
(
bean_name
=
'crisis_one'
)
@
component
(
bean_name
=
'crisis_one'
)
class
CrisisOneSignal
(
CrisisSignal
,
Base
SignalBuilder
):
class
CrisisOneSignal
(
CrisisSignal
,
Base
RebalanceSignal
):
@
property
@
property
def
consecut_days
(
self
):
def
consecut_days
(
self
):
...
@@ -84,7 +84,7 @@ class CrisisOneSignal(CrisisSignal, BaseSignalBuilder):
...
@@ -84,7 +84,7 @@ class CrisisOneSignal(CrisisSignal, BaseSignalBuilder):
@
component
(
bean_name
=
'crisis_two'
)
@
component
(
bean_name
=
'crisis_two'
)
class
CrisisTwoSignal
(
CrisisSignal
,
Base
SignalBuilder
):
class
CrisisTwoSignal
(
CrisisSignal
,
Base
RebalanceSignal
):
@
property
@
property
def
negative_growth_years
(
self
):
def
negative_growth_years
(
self
):
...
...
rebalance/signals/curve_drift.py
View file @
bf40eee2
from
api
import
PortfoliosRisk
,
SignalType
,
Datum
,
PortfoliosHolder
,
DriftSolver
from
api
import
PortfoliosRisk
,
SignalType
,
Datum
,
PortfoliosHolder
,
DriftSolver
from
framework
import
component
,
autowired
,
get_config
from
framework
import
component
,
autowired
,
get_config
from
rebalance.base_signal
import
Base
SignalBuilder
from
rebalance.base_signal
import
Base
RebalanceSignal
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
@
component
(
bean_name
=
'curve-drift'
)
@
component
(
bean_name
=
'curve-drift'
)
class
CurveDrift
(
Base
SignalBuilder
):
class
CurveDrift
(
Base
RebalanceSignal
):
@
autowired
(
names
=
{
'solver'
:
'date-curve'
})
@
autowired
(
names
=
{
'solver'
:
'date-curve'
})
def
__init__
(
self
,
datum
:
Datum
=
None
,
hold
:
PortfoliosHolder
=
None
,
solver
:
DriftSolver
=
None
):
def
__init__
(
self
,
datum
:
Datum
=
None
,
hold
:
PortfoliosHolder
=
None
,
solver
:
DriftSolver
=
None
):
...
...
rebalance/signals/high_low_buy.py
View file @
bf40eee2
...
@@ -2,12 +2,12 @@ import pandas as pd
...
@@ -2,12 +2,12 @@ import pandas as pd
from
api
import
PortfoliosBuilder
,
SignalType
,
PortfoliosRisk
,
Datum
,
DriftSolver
from
api
import
PortfoliosBuilder
,
SignalType
,
PortfoliosRisk
,
Datum
,
DriftSolver
from
framework
import
component
,
autowired
,
get_config
,
filter_weekend
,
next_workday
,
is_workday
from
framework
import
component
,
autowired
,
get_config
,
filter_weekend
,
next_workday
,
is_workday
from
rebalance.base_signal
import
Base
SignalBuilder
from
rebalance.base_signal
import
Base
RebalanceSignal
from
rebalance.dao
import
robo_weight_drift
as
rwd
,
robo_rebalance_signal
as
rrs
from
rebalance.dao
import
robo_weight_drift
as
rwd
,
robo_rebalance_signal
as
rrs
@
component
(
bean_name
=
'high-buy'
)
@
component
(
bean_name
=
'high-buy'
)
class
HighBuySignal
(
Base
SignalBuilder
):
class
HighBuySignal
(
Base
RebalanceSignal
):
@
autowired
(
names
=
{
'solver'
:
'high-weight'
})
@
autowired
(
names
=
{
'solver'
:
'high-weight'
})
def
__init__
(
self
,
solver
:
DriftSolver
=
None
):
def
__init__
(
self
,
solver
:
DriftSolver
=
None
):
...
...
rebalance/signals/init_signal.py
View file @
bf40eee2
from
api
import
PortfoliosRisk
,
SignalType
from
api
import
PortfoliosRisk
,
SignalType
from
framework
import
component
from
framework
import
component
from
rebalance.base_signal
import
Base
SignalBuilder
from
rebalance.base_signal
import
Base
RebalanceSignal
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
@
component
(
bean_name
=
'init'
)
@
component
(
bean_name
=
'init'
)
class
InitSignalBuilder
(
Base
SignalBuilder
):
class
InitSignalBuilder
(
Base
RebalanceSignal
):
@
property
@
property
def
signal_type
(
self
)
->
SignalType
:
def
signal_type
(
self
)
->
SignalType
:
...
...
rebalance/signals/right_side.py
View file @
bf40eee2
...
@@ -3,12 +3,12 @@ from scipy.stats import norm
...
@@ -3,12 +3,12 @@ from scipy.stats import norm
from
api
import
SignalType
,
PortfoliosRisk
,
Navs
from
api
import
SignalType
,
PortfoliosRisk
,
Navs
from
framework
import
component
,
autowired
,
get_config
from
framework
import
component
,
autowired
,
get_config
from
rebalance.base_signal
import
Base
SignalBuilder
from
rebalance.base_signal
import
Base
RebalanceSignal
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
from
rebalance.dao
import
robo_rebalance_signal
as
rrs
@
component
(
bean_name
=
'market-right'
)
@
component
(
bean_name
=
'market-right'
)
class
MarketRight
(
Base
SignalBuilder
):
class
MarketRight
(
Base
RebalanceSignal
):
@
autowired
@
autowired
def
__init__
(
self
,
navs
:
Navs
=
None
):
def
__init__
(
self
,
navs
:
Navs
=
None
):
...
...
rebalance/test_case.py
View file @
bf40eee2
import
unittest
import
unittest
from
api
import
SignalBuilder
,
PortfoliosRisk
,
RebalanceBuild
er
from
api
import
RebalanceSignal
,
PortfoliosRisk
,
RebalanceRul
er
from
framework
import
autowired
,
parse_date
,
get_logger
from
framework
import
autowired
,
parse_date
,
get_logger
...
@@ -9,27 +9,27 @@ class RebalanceTest(unittest.TestCase):
...
@@ -9,27 +9,27 @@ class RebalanceTest(unittest.TestCase):
logger
=
get_logger
(
__name__
)
logger
=
get_logger
(
__name__
)
@
autowired
(
names
=
{
'builder'
:
'crisis_one'
})
@
autowired
(
names
=
{
'builder'
:
'crisis_one'
})
def
test_crisis_one
(
self
,
builder
:
SignalBuilder
=
None
):
def
test_crisis_one
(
self
,
builder
:
RebalanceSignal
=
None
):
signal
=
builder
.
get_signal
(
parse_date
(
'2022-10-13'
),
PortfoliosRisk
.
FT9
)
signal
=
builder
.
get_signal
(
parse_date
(
'2022-10-13'
),
PortfoliosRisk
.
FT9
)
self
.
logger
.
info
(
signal
)
self
.
logger
.
info
(
signal
)
@
autowired
(
names
=
{
'builder'
:
'market-right'
})
@
autowired
(
names
=
{
'builder'
:
'market-right'
})
def
test_market_right
(
self
,
builder
:
SignalBuilder
=
None
):
def
test_market_right
(
self
,
builder
:
RebalanceSignal
=
None
):
signal
=
builder
.
get_signal
(
parse_date
(
'2022-10-13'
),
PortfoliosRisk
.
FT9
)
signal
=
builder
.
get_signal
(
parse_date
(
'2022-10-13'
),
PortfoliosRisk
.
FT9
)
self
.
logger
.
info
(
signal
)
self
.
logger
.
info
(
signal
)
@
autowired
(
names
=
{
'builder'
:
'curve-drift'
})
@
autowired
(
names
=
{
'builder'
:
'curve-drift'
})
def
test_curve_drift
(
self
,
builder
:
SignalBuilder
=
None
):
def
test_curve_drift
(
self
,
builder
:
RebalanceSignal
=
None
):
signal
=
builder
.
get_signal
(
parse_date
(
'2022-11-07'
),
PortfoliosRisk
.
FT3
)
signal
=
builder
.
get_signal
(
parse_date
(
'2022-11-07'
),
PortfoliosRisk
.
FT3
)
self
.
logger
.
info
(
signal
)
self
.
logger
.
info
(
signal
)
@
autowired
(
names
=
{
'builder'
:
'high-buy'
})
@
autowired
(
names
=
{
'builder'
:
'high-buy'
})
def
test_high_buy
(
self
,
builder
:
SignalBuilder
=
None
):
def
test_high_buy
(
self
,
builder
:
RebalanceSignal
=
None
):
builder
.
get_signal
(
parse_date
(
'2022-09-10'
),
PortfoliosRisk
.
FT3
)
builder
.
get_signal
(
parse_date
(
'2022-09-10'
),
PortfoliosRisk
.
FT3
)
@
autowired
@
autowired
def
test_rebalance_builder
(
self
,
builder
:
Rebalance
Build
er
=
None
):
def
test_rebalance_builder
(
self
,
builder
:
Rebalance
Rul
er
=
None
):
builder
.
get_rebalance
(
parse_date
(
'2022-09-01'
),
PortfoliosRisk
.
FT3
)
builder
.
take_next_signal
(
parse_date
(
'2022-09-01'
),
PortfoliosRisk
.
FT3
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
...
...
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