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
d66b12eb
Commit
d66b12eb
authored
Nov 09, 2022
by
jichao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
基金优选完成
parent
c023f84d
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
136 additions
and
20 deletions
+136
-20
config.yml
config.yml
+5
-0
api.py
datas/datum/api.py
+5
-1
mysql.sql
datas/mysql.sql
+30
-0
__init__.py
datas/navs/__init__.py
+4
-2
api.py
datas/navs/api.py
+32
-0
robo_exrate.py
datas/navs/robo_exrate.py
+26
-0
fund_optimize.py
fund_pool/fund_optimize.py
+9
-16
base.py
utils/base.py
+25
-1
No files found.
config.yml
View file @
d66b12eb
...
...
@@ -45,6 +45,11 @@ logger:
root
:
level
:
INFO
handlers
:
[
console
]
datas
:
navs
:
exrate
:
-
from
:
EUR
ticker
:
EURUSD BGN Curncy
fund_pool
:
fund_optimize
:
sortino_weight
:
...
...
datas/datum/api.py
View file @
d66b12eb
...
...
@@ -2,9 +2,13 @@ import datas.datum.robo_base_datum as _rbd
from
datas.datum.enums
import
DatumType
def
get_fund_datums
(
crncy
=
None
,
risk
=
None
):
def
get_fund_datums
(
crncy
=
None
,
risk
=
None
,
fund_ids
=
None
):
return
_rbd
.
get_base_datums
(
type
=
DatumType
.
FUND
,
crncy
=
crncy
,
risk
=
risk
)
def
get_without_crncy
(
crncy
):
pass
if
__name__
==
'__main__'
:
print
(
get_fund_datums
(
risk
=
1
))
datas/mysql.sql
View file @
d66b12eb
...
...
@@ -38,3 +38,33 @@ CREATE TABLE IF NOT EXISTS robo_fund_navs
)
ENGINE
=
InnoDB
DEFAULT
CHARSET
=
utf8mb4
COMMENT
'基金数据表'
;
CREATE
TABLE
IF
NOT
EXISTS
`robo_exrate`
(
`re_id`
BIGINT
UNSIGNED
NOT
NULL
AUTO_INCREMENT
,
`re_ticker`
VARCHAR
(
255
)
NOT
NULL
COMMENT
'汇率ticker'
,
`re_date`
DATETIME
NOT
NULL
COMMENT
'日期'
,
`re_close`
DOUBLE
NOT
NULL
COMMENT
'收盘价'
,
`re_create_time`
DATETIME
NOT
NULL
DEFAULT
CURRENT_TIMESTAMP
,
`re_update_time`
DATETIME
DEFAULT
NULL
ON
UPDATE
CURRENT_TIMESTAMP
,
PRIMARY
KEY
(
`re_id`
),
UNIQUE
(
`re_ticker`
,
`re_date`
),
INDEX
(
`re_date`
)
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
0
DEFAULT
CHARSET
=
utf8mb4
COMMENT
'基金数据表'
;
CREATE
TABLE
IF
NOT
EXISTS
robo_optimize_pool
(
rop_id
BIGINT
UNSIGNED
NOT
NULL
AUTO_INCREMENT
,
rop_date
DATETIME
NOT
NULL
COMMENT
'数据日期'
,
rop_fund_ids
JSON
DEFAULT
NULL
COMMENT
'基金ID'
,
rop_create_time
DATETIME
NOT
NULL
DEFAULT
CURRENT_TIMESTAMP
,
rop_update_time
DATETIME
DEFAULT
NULL
ON
UPDATE
CURRENT_TIMESTAMP
,
PRIMARY
KEY
(
rop_id
),
INDEX
(
rop_date
)
)
ENGINE
=
InnoDB
AUTO_INCREMENT
=
0
DEFAULT
CHARSET
=
utf8mb4
COMMENT
'优选基金池'
;
datas/navs/__init__.py
View file @
d66b12eb
from
.robo_fund_navs
import
*
from
.api
import
(
get_navs
)
del
robo_fund_navs
del
api
datas/navs/api.py
0 → 100644
View file @
d66b12eb
import
pandas
as
_pd
from
datas.navs
import
robo_exrate
as
_re
,
robo_fund_navs
as
_navs
from
datas
import
datum
as
_datum
,
DatumType
from
utils
import
config
,
to_bool
from
datetime
import
timedelta
navs_config
=
config
[
'datas'
][
'navs'
]
if
'datas'
in
config
and
'navs'
in
config
[
'datas'
]
else
{}
def
get_navs
(
fund_id
=
None
,
min_date
=
None
,
max_date
=
None
):
navs
=
_navs
.
get_navs
(
fund_id
=
fund_id
,
min_date
=
min_date
,
max_date
=
max_date
)
if
'exrate'
in
navs_config
:
navs
=
_pd
.
DataFrame
(
navs
)
navs
=
navs
.
pivot_table
(
index
=
'nav_date'
,
columns
=
'fund_id'
,
values
=
'nav_cal'
)
for
exrate_config
in
navs_config
[
'exrate'
]:
exrate
=
_pd
.
DataFrame
(
_re
.
get_exrates
(
ticker
=
exrate_config
[
'ticker'
],
min_date
=
navs
.
index
.
min
(),
max_date
=
navs
.
index
.
max
()))
exrate
=
exrate
[[
'date'
,
'close'
]]
exrate
.
set_index
(
'date'
,
inplace
=
True
)
for
fund
in
_datum
.
get_fund_datums
(
crncy
=
exrate_config
[
'from'
]):
navs
[
fund
[
'id'
]]
=
round
(
navs
[
fund
[
'id'
]]
*
exrate
[
'close'
],
4
)
navs
=
navs
.
reset_index
()
.
melt
(
id_vars
=
'nav_date'
,
value_name
=
'nav_cal'
)
navs
.
dropna
(
inplace
=
True
)
navs
=
navs
[[
'fund_id'
,
'nav_date'
,
'nav_cal'
]]
navs
.
sort_values
(
'fund_id'
,
inplace
=
True
)
navs
=
navs
.
to_dict
(
'records'
)
return
navs
if
__name__
==
'__main__'
:
from
utils
import
parse_date
print
(
get_navs
(
min_date
=
parse_date
(
'2022-11-01'
)))
datas/navs/robo_exrate.py
0 → 100644
View file @
d66b12eb
from
utils
import
read
,
where
,
format_date
@
read
def
_select
(
*
args
,
**
kwargs
):
return
f
'''select re_id as id, re_ticker as ticker, re_date as date, re_close as close from robo_exrate {where(*args, **kwargs)}'''
def
get_exrates
(
ticker
=
None
,
min_date
=
None
,
max_date
=
None
):
sqls
=
[]
if
min_date
:
sqls
.
append
(
f
"re_date >= '{format_date(min_date)}'"
)
if
max_date
:
sqls
.
append
(
f
"re_date <= '{format_date(max_date)}'"
)
return
_select
(
*
sqls
,
re_ticker
=
ticker
)
@
read
(
one
=
True
)
def
get_exrate
(
ticker
,
date
):
return
f
'''select re_id as id, re_ticker as ticker, re_date as date, re_close as close from robo_exrate {where(re_ticker=ticker, re_date=date)}'''
if
__name__
==
'__main__'
:
from
utils
import
parse_date
print
(
get_exrate
(
date
=
parse_date
(
'2022-11-01'
),
ticker
=
'EURUSD BGN Curncy'
))
fund_pool/fund_optimize.py
View file @
d66b12eb
...
...
@@ -4,11 +4,14 @@ from datas import navs
from
dateutil.relativedelta
import
relativedelta
from
empyrical
import
sortino_ratio
optimize_config
=
config
[
'fund_pool'
][
'fund_optimize'
]
sortino_config
=
[{
**
x
,
'name'
:
[
f
"sortino_{y[1]}_{y[0]}"
for
y
in
x
.
items
()
if
y
[
0
]
!=
'weight'
][
0
]}
for
x
in
optimize_config
[
'sortino_weight'
]]
optimize_config
=
config
[
'fund_pool'
][
'fund_optimize'
]
if
'fund_pool'
in
config
and
'fund_optimize'
in
config
[
'fund_pool'
]
else
{}
sortino_config
=
[{
**
x
,
'name'
:
[
f
"sortino_{y[1]}_{y[0]}"
for
y
in
x
.
items
()
if
y
[
0
]
!=
'weight'
][
0
]}
for
x
in
optimize_config
[
'sortino_weight'
]]
\
if
'sortino_weight'
in
optimize_config
else
[]
def
find_optimize
(
fund_ids
,
day
):
if
not
sortino_config
:
raise
NameError
(
f
"find optimize, but not found sortino config."
)
start
=
filter_weekend
(
sorted
([
day
-
relativedelta
(
days
=
1
,
**
dict_remove
(
x
,
(
'weight'
,
'name'
)))
for
x
in
sortino_config
])[
0
])
fund_navs
=
pd
.
DataFrame
(
navs
.
get_navs
(
fund_id
=
tuple
(
fund_ids
),
min_date
=
start
,
max_date
=
day
))
fund_navs
.
sort_values
(
'nav_date'
,
inplace
=
True
)
...
...
@@ -17,31 +20,21 @@ def find_optimize(fund_ids, day):
day_income
=
round
(
fund_navs
.
pct_change
(),
4
)
sortino
=
pd
.
DataFrame
()
for
item
in
sortino_config
:
delta_kwargs
=
{
**
item
}
delta_kwargs
=
item
.
copy
()
del
delta_kwargs
[
'weight'
],
delta_kwargs
[
'name'
]
ratio
=
dict
(
sortino_ratio
(
day_income
.
truncate
(
before
=
(
day
-
relativedelta
(
**
delta_kwargs
)))))
sortino
=
pd
.
concat
([
sortino
,
pd
.
DataFrame
([
ratio
],
index
=
[
item
[
'name'
]])])
sortino
=
sortino
.
T
sortino
[
'score'
]
=
sortino
.
apply
(
lambda
r
:
sum
([
x
[
'weight'
]
*
r
[
x
[
'name'
]]
for
x
in
sortino_config
]),
axis
=
1
)
sortino
[
'score'
]
=
sortino
.
apply
(
lambda
r
:
sum
([
x
[
'weight'
]
*
r
[
x
[
'name'
]]
for
x
in
sortino_config
]),
axis
=
1
)
sortino
.
sort_values
(
'score'
,
ascending
=
False
,
inplace
=
True
)
return
day_income
.
columns
[
sortino
.
index
[
0
]]
def
get_
base_fund_pool
(
):
def
get_
optimize_fund_pool
(
day
):
pass
if
__name__
==
'__main__'
:
from
datas
import
datum
from
datetime
import
date
funds
=
datum
.
get_fund_datums
()
funds
=
pd
.
DataFrame
(
funds
)
for
(
category
,
assetType
),
fund_group
in
funds
.
groupby
(
by
=
[
'category'
,
'assetType'
]):
if
len
(
fund_group
)
>
1
:
fund_ids
=
tuple
(
fund_group
[
'id'
])
fund_id
=
find_optimize
(
fund_ids
,
date
.
today
())
print
(
fund_ids
,
"->"
,
fund_id
)
else
:
fund_ids
=
tuple
(
fund_group
[
'id'
])
print
(
fund_ids
,
"->"
,
fund_ids
[
0
])
get_optimize_fund_pool
(
date
.
today
())
utils/base.py
View file @
d66b12eb
import
os
from
functools
import
reduce
__all__
=
[
'get_project_path'
,
'deep_dict_update'
,
'dict_remove'
]
__all__
=
[
'get_project_path'
,
'deep_dict_update'
,
'dict_remove'
,
'equals_ignore_case'
,
'to_bool'
,
]
def
get_project_path
():
...
...
@@ -36,3 +43,20 @@ def dict_remove(d: dict, k) -> dict:
for
key
in
tuple
(
k
):
del
result
[
key
]
return
result
def
equals_ignore_case
(
a
,
b
)
->
bool
:
return
str
(
a
)
.
upper
()
==
str
(
b
)
.
upper
()
if
a
and
b
else
False
_TRUE_STR
=
[
'true'
,
't'
,
'yes'
,
'y'
,
'on'
]
_FALSE_STR
=
[
'false'
,
'f'
,
'no'
,
'n'
,
'off'
]
def
to_bool
(
v
)
->
bool
:
if
isinstance
(
v
,
str
):
if
reduce
(
lambda
a
,
b
:
a
or
b
,
[
equals_ignore_case
(
v
,
x
)
for
x
in
_TRUE_STR
]):
return
True
if
reduce
(
lambda
a
,
b
:
a
or
b
,
[
equals_ignore_case
(
v
,
x
)
for
x
in
_FALSE_STR
]):
return
False
return
bool
(
v
)
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