Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
A
alpha-mind
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
Dr.李
alpha-mind
Commits
c8079091
Commit
c8079091
authored
Sep 28, 2017
by
Dr.李
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://git.coding.net/wegamekinglc/Alpha-Mind
parents
ddf70a43
baca9696
Changes
24
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
1044 additions
and
27 deletions
+1044
-27
.travis.yml
.travis.yml
+2
-8
README.md
README.md
+1
-0
factoranalysis.py
alphamind/analysis/factoranalysis.py
+1
-1
api.py
alphamind/api.py
+9
-0
models.py
alphamind/data/dbmodel/models.py
+60
-3
__init__.py
alphamind/execution/__init__.py
+0
-0
baseexecutor.py
alphamind/execution/baseexecutor.py
+35
-0
naiveexecutor.py
alphamind/execution/naiveexecutor.py
+24
-0
pipeline.py
alphamind/execution/pipeline.py
+36
-0
targetvolexecutor.py
alphamind/execution/targetvolexecutor.py
+45
-0
thresholdexecutor.py
alphamind/execution/thresholdexecutor.py
+32
-0
composer.py
alphamind/model/composer.py
+146
-0
data_preparing.py
alphamind/model/data_preparing.py
+2
-2
rankbuilder.py
alphamind/portfolio/rankbuilder.py
+6
-1
sample_strategy.json
alphamind/strategy/sample_strategy.json
+18
-6
__init__.py
alphamind/tests/execution/__init__.py
+0
-0
test_naiveexecutor.py
alphamind/tests/execution/test_naiveexecutor.py
+45
-0
test_pipeline.py
alphamind/tests/execution/test_pipeline.py
+45
-0
test_targetvolexecutor.py
alphamind/tests/execution/test_targetvolexecutor.py
+51
-0
test_thresholdexecutor.py
alphamind/tests/execution/test_thresholdexecutor.py
+50
-0
test_rankbuild.py
alphamind/tests/portfolio/test_rankbuild.py
+28
-4
test_suite.py
alphamind/tests/test_suite.py
+7
-1
executor_example.ipynb
notebooks/executor_example.ipynb
+400
-0
create_view.sql
scripts/create_view.sql
+1
-1
No files found.
.travis.yml
View file @
c8079091
...
...
@@ -10,22 +10,16 @@ addons:
packages
:
-
libblas-dev
-
liblapack-dev
-
gcc
-
gfortran
install
:
# We do this conditionally because it saves us some downloading if the
# version is the same.
-
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
-
sudo apt-get -qq update
-
sudo apt-get -qq install g++-5
-
sudo apt-get -qq install gcc-5
# - export CXX="g++-6" CC="gcc-6"
-
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 60 --slave /usr/bin/g++ g++ /usr/bin/g++-5
-
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
-
wget https://repo.continuum.io/miniconda/Miniconda3-4.3.21-Linux-x86_64.sh -O miniconda.sh
-
bash miniconda.sh -b -p $HOME/miniconda
-
export PATH="$HOME/miniconda/bin:$PATH"
-
hash -r
-
conda config --set always_yes yes --set changeps1 no
-
conda update -q conda
# Useful for debugging any issues with conda
-
conda info -a
# Replace dep1 dep2 ... with your dependencies
...
...
README.md
View file @
c8079091
...
...
@@ -25,6 +25,7 @@ alpha - mind 提供了多因子研究中常用的工具链,包括:
*
alpha 模型
*
风险模型
*
组合优化
*
执行器
所有的模块都设计了完整的测试用例以尽可能保证正确性。同时,所有的数值模型开发中都对性能给予了足够高的关注,参考了优秀的第三方工具以保证性能:
...
...
alphamind/analysis/factoranalysis.py
View file @
c8079091
...
...
@@ -99,7 +99,7 @@ def er_portfolio_analysis(er: np.ndarray,
raise
ValueError
(
'linear programming optimizer in status: {0}'
.
format
(
status
))
elif
method
==
'rank'
:
weights
=
rank_build
(
er
,
use_rank
=
kwargs
[
'use_rank'
])
.
flatten
()
*
benchmark
.
sum
()
/
kwargs
[
'use_rank'
]
weights
=
rank_build
(
er
,
use_rank
=
kwargs
[
'use_rank'
]
,
masks
=
is_tradable
)
.
flatten
()
*
benchmark
.
sum
()
/
kwargs
[
'use_rank'
]
elif
method
==
'ls'
or
method
==
'long_short'
:
weights
=
long_short_build
(
er
)
.
flatten
()
elif
method
==
'mv'
or
method
==
'mean_variance'
:
...
...
alphamind/api.py
View file @
c8079091
...
...
@@ -28,6 +28,11 @@ from alphamind.model.linearmodel import ConstLinearModel
from
alphamind.model.loader
import
load_model
from
alphamind.model.data_preparing
import
fetch_data_package
from
alphamind.execution.naiveexecutor
import
NaiveExecutor
from
alphamind.execution.thresholdexecutor
import
ThresholdExecutor
from
alphamind.execution.targetvolexecutor
import
TargetVolExecutor
from
alphamind.execution.pipeline
import
ExecutionPipeline
from
alphamind.utilities
import
alpha_logger
...
...
@@ -52,5 +57,9 @@ __all__ = [
'LinearRegression'
,
'ConstLinearModel'
,
'load_model'
,
'NaiveExecutor'
,
'ThresholdExecutor'
,
'TargetVolExecutor'
,
'ExecutionPipeline'
,
'alpha_logger'
]
\ No newline at end of file
alphamind/data/dbmodel/models.py
View file @
c8079091
...
...
@@ -1179,6 +1179,63 @@ class Experimental(Base):
DROEAfterNonRecurring
=
Column
(
Float
(
53
))
CFinc1
=
Column
(
Float
(
53
))
xueqiu_hotness
=
Column
(
Float
(
53
))
con_eps
=
Column
(
Float
(
53
))
con_pb
=
Column
(
Float
(
53
))
con_pb_order
=
Column
(
Float
(
53
))
con_pb_rolling
=
Column
(
Float
(
53
))
con_pb_rolling_order
=
Column
(
Float
(
53
))
con_pe
=
Column
(
Float
(
53
))
con_pe_order
=
Column
(
Float
(
53
))
con_pe_rolling
=
Column
(
Float
(
53
))
con_pe_rolling_order
=
Column
(
Float
(
53
))
con_peg
=
Column
(
Float
(
53
))
con_peg_order
=
Column
(
Float
(
53
))
con_peg_rolling
=
Column
(
Float
(
53
))
con_peg_rolling_order
=
Column
(
Float
(
53
))
con_ps
=
Column
(
Float
(
53
))
con_ps_order
=
Column
(
Float
(
53
))
con_ps_rolling
=
Column
(
Float
(
53
))
con_ps_rolling_order
=
Column
(
Float
(
53
))
con_target_price
=
Column
(
Float
(
53
))
market_confidence_10d
=
Column
(
Float
(
53
))
market_confidence_15d
=
Column
(
Float
(
53
))
market_confidence_25d
=
Column
(
Float
(
53
))
market_confidence_5d
=
Column
(
Float
(
53
))
market_confidence_75d
=
Column
(
Float
(
53
))
optimism_confidence_10d
=
Column
(
Float
(
53
))
optimism_confidence_15d
=
Column
(
Float
(
53
))
optimism_confidence_25d
=
Column
(
Float
(
53
))
optimism_confidence_5d
=
Column
(
Float
(
53
))
optimism_confidence_75d
=
Column
(
Float
(
53
))
pessimism_confidence_10d
=
Column
(
Float
(
53
))
pessimism_confidence_15d
=
Column
(
Float
(
53
))
pessimism_confidence_25d
=
Column
(
Float
(
53
))
pessimism_confidence_5d
=
Column
(
Float
(
53
))
pessimism_confidence_75d
=
Column
(
Float
(
53
))
con_na_yoy
=
Column
(
Float
(
53
))
con_np_yoy
=
Column
(
Float
(
53
))
con_npcgrate_13w
=
Column
(
Float
(
53
))
con_npcgrate_1w
=
Column
(
Float
(
53
))
con_npcgrate_26w
=
Column
(
Float
(
53
))
con_npcgrate_2y
=
Column
(
Float
(
53
))
con_npcgrate_4w
=
Column
(
Float
(
53
))
con_npcgrate_52w
=
Column
(
Float
(
53
))
con_or_yoy
=
Column
(
Float
(
53
))
con_roe_yoy1
=
Column
(
Float
(
53
))
con_roe_yoy2
=
Column
(
Float
(
53
))
con_roe_yoy3
=
Column
(
Float
(
53
))
con_eps_rolling
=
Column
(
Float
(
53
))
con_np
=
Column
(
Float
(
53
))
con_np_rolling
=
Column
(
Float
(
53
))
con_or
=
Column
(
Float
(
53
))
con_or_rolling
=
Column
(
Float
(
53
))
con_roe
=
Column
(
Float
(
53
))
con_na
=
Column
(
Float
(
53
))
con_na_rolling
=
Column
(
Float
(
53
))
mcap
=
Column
(
Float
(
53
))
tcap
=
Column
(
Float
(
53
))
ta
=
Column
(
Float
(
53
))
na
=
Column
(
Float
(
53
))
class
FactorMaster
(
Base
):
...
...
@@ -1366,7 +1423,7 @@ class Models(Base):
model_version
=
Column
(
BigInteger
,
nullable
=
False
)
update_time
=
Column
(
DateTime
,
nullable
=
False
)
model_desc
=
Column
(
JSONB
,
nullable
=
False
)
is_primary
=
Column
(
Boolean
,
default
=
False
)
is_primary
=
Column
(
Boolean
)
model_id
=
Column
(
Integer
,
primary_key
=
True
,
server_default
=
text
(
"nextval('models_model_id_seq'::regclass)"
))
...
...
@@ -1402,12 +1459,12 @@ class PnlLog(Base):
class
PortfolioSettings
(
Base
):
__tablename__
=
'portfolio_settings'
__table_args__
=
(
Index
(
'portfolio_pk'
,
'trade_date'
,
'portfolio_name'
,
unique
=
True
),
Index
(
'portfolio_pk'
,
'trade_date'
,
'portfolio_name'
,
'model_id'
,
unique
=
True
),
)
trade_date
=
Column
(
DateTime
,
primary_key
=
True
,
nullable
=
False
)
portfolio_name
=
Column
(
String
(
50
),
primary_key
=
True
,
nullable
=
False
)
model_id
=
Column
(
BigInteger
,
nullable
=
False
)
model_id
=
Column
(
BigInteger
,
primary_key
=
True
,
nullable
=
False
)
class
Positions
(
Base
):
...
...
alphamind/execution/__init__.py
0 → 100644
View file @
c8079091
alphamind/execution/baseexecutor.py
0 → 100644
View file @
c8079091
# -*- coding: utf-8 -*-
"""
Created on 2017-9-22
@author: cheng.li
"""
import
abc
from
typing
import
Tuple
import
numpy
as
np
import
pandas
as
pd
class
ExecutorBase
(
metaclass
=
abc
.
ABCMeta
):
def
__init__
(
self
):
self
.
current_pos
=
pd
.
DataFrame
()
@
abc
.
abstractmethod
def
execute
(
self
,
target_pos
:
pd
.
DataFrame
)
->
pd
.
DataFrame
:
pass
@
staticmethod
def
calc_turn_over
(
target_pos
:
pd
.
DataFrame
,
current_pos
:
pd
.
DataFrame
)
->
float
:
pos_merged
=
pd
.
merge
(
target_pos
,
current_pos
,
on
=
[
'code'
],
how
=
'outer'
)
pos_merged
.
fillna
(
0
,
inplace
=
True
)
turn_over
=
np
.
abs
(
pos_merged
.
weight_x
-
pos_merged
.
weight_y
)
.
sum
()
return
turn_over
def
set_current
(
self
,
current_pos
:
pd
.
DataFrame
):
self
.
current_pos
=
current_pos
.
copy
()
def
update
(
self
,
data_dict
:
dict
):
pass
alphamind/execution/naiveexecutor.py
0 → 100644
View file @
c8079091
# -*- coding: utf-8 -*-
"""
Created on 2017-9-22
@author: cheng.li
"""
from
typing
import
Tuple
import
pandas
as
pd
from
alphamind.execution.baseexecutor
import
ExecutorBase
class
NaiveExecutor
(
ExecutorBase
):
def
__init__
(
self
):
super
()
.
__init__
()
def
execute
(
self
,
target_pos
:
pd
.
DataFrame
)
->
Tuple
[
float
,
pd
.
DataFrame
]:
if
self
.
current_pos
.
empty
:
turn_over
=
target_pos
.
weight
.
abs
()
.
sum
()
else
:
turn_over
=
self
.
calc_turn_over
(
target_pos
,
self
.
current_pos
)
self
.
current_pos
=
target_pos
.
copy
()
return
turn_over
,
target_pos
alphamind/execution/pipeline.py
0 → 100644
View file @
c8079091
# -*- coding: utf-8 -*-
"""
Created on 2017-9-25
@author: cheng.li
"""
from
typing
import
List
from
typing
import
Tuple
import
pandas
as
pd
from
alphamind.execution.baseexecutor
import
ExecutorBase
class
ExecutionPipeline
(
object
):
def
__init__
(
self
,
executors
:
List
[
ExecutorBase
]):
self
.
executors
=
executors
def
execute
(
self
,
target_pos
)
->
Tuple
[
float
,
pd
.
DataFrame
]:
turn_over
,
planed_pos
=
0.
,
target_pos
for
executor
in
self
.
executors
:
turn_over
,
planed_pos
=
executor
.
execute
(
planed_pos
)
executed_pos
=
planed_pos
for
executor
in
self
.
executors
:
executor
.
set_current
(
executed_pos
)
return
turn_over
,
executed_pos
def
update
(
self
,
data_dict
):
for
executor
in
self
.
executors
:
executor
.
update
(
data_dict
=
data_dict
)
alphamind/execution/targetvolexecutor.py
0 → 100644
View file @
c8079091
# -*- coding: utf-8 -*-
"""
Created on 2017-9-22
@author: cheng.li
"""
from
typing
import
Tuple
import
pandas
as
pd
from
PyFin.Math.Accumulators
import
MovingStandardDeviation
from
PyFin.Math.Accumulators
import
MovingAverage
from
alphamind.execution.baseexecutor
import
ExecutorBase
class
TargetVolExecutor
(
ExecutorBase
):
def
__init__
(
self
,
window
=
30
,
target_vol
=
0.01
):
super
()
.
__init__
()
self
.
m_vol
=
MovingStandardDeviation
(
window
=
window
,
dependency
=
'return'
)
self
.
m_leverage
=
MovingAverage
(
window
=
window
,
dependency
=
'leverage'
)
self
.
target_vol
=
target_vol
self
.
multiplier
=
1.
def
execute
(
self
,
target_pos
:
pd
.
DataFrame
)
->
Tuple
[
float
,
pd
.
DataFrame
]:
if
not
self
.
m_vol
.
isFull
():
if
self
.
current_pos
.
empty
:
turn_over
=
target_pos
.
weight
.
abs
()
.
sum
()
else
:
turn_over
=
self
.
calc_turn_over
(
target_pos
,
self
.
current_pos
)
return
turn_over
,
target_pos
else
:
c_vol
=
self
.
m_vol
.
result
()
c_leverage
=
self
.
m_leverage
.
result
()
self
.
multiplier
=
self
.
target_vol
/
c_vol
*
c_leverage
candidate_pos
=
target_pos
.
copy
()
candidate_pos
[
'weight'
]
=
candidate_pos
.
weight
.
values
*
self
.
multiplier
turn_over
=
self
.
calc_turn_over
(
candidate_pos
,
self
.
current_pos
)
return
turn_over
,
candidate_pos
def
set_current
(
self
,
current_pos
:
pd
.
DataFrame
):
super
()
.
set_current
(
current_pos
)
self
.
m_leverage
.
push
({
'leverage'
:
current_pos
.
weight
.
abs
()
.
sum
()})
def
update
(
self
,
data_dict
:
dict
):
self
.
m_vol
.
push
(
data_dict
)
alphamind/execution/thresholdexecutor.py
0 → 100644
View file @
c8079091
# -*- coding: utf-8 -*-
"""
Created on 2017-9-22
@author: cheng.li
"""
from
typing
import
Tuple
import
pandas
as
pd
from
alphamind.execution.baseexecutor
import
ExecutorBase
class
ThresholdExecutor
(
ExecutorBase
):
def
__init__
(
self
,
turn_over_threshold
:
float
,
is_relative
=
True
):
super
()
.
__init__
()
self
.
threshold
=
turn_over_threshold
self
.
is_relative
=
is_relative
def
execute
(
self
,
target_pos
:
pd
.
DataFrame
)
->
Tuple
[
float
,
pd
.
DataFrame
]:
if
self
.
current_pos
.
empty
:
return
target_pos
.
weight
.
abs
()
.
sum
(),
target_pos
else
:
turn_over
=
self
.
calc_turn_over
(
target_pos
,
self
.
current_pos
)
is_break
=
turn_over
>=
self
.
threshold
*
self
.
current_pos
.
weight
.
sum
()
if
self
.
is_relative
else
turn_over
>=
self
.
threshold
if
is_break
:
return
turn_over
,
target_pos
else
:
return
0.
,
self
.
current_pos
.
copy
()
alphamind/model/composer.py
0 → 100644
View file @
c8079091
# -*- coding: utf-8 -*-
"""
Created on 2017-9-27
@author: cheng.li
"""
import
copy
import
bisect
from
typing
import
Union
from
typing
import
Iterable
import
pandas
as
pd
from
alphamind.model.modelbase
import
ModelBase
from
alphamind.model.data_preparing
import
fetch_train_phase
from
alphamind.model.data_preparing
import
fetch_predict_phase
from
alphamind.data.transformer
import
Transformer
from
alphamind.data.engines.universe
import
Universe
class
DataMeta
(
object
):
def
__init__
(
self
,
engine
,
alpha_factors
:
Union
[
Transformer
,
Iterable
[
object
]],
freq
:
str
,
universe
:
Universe
,
batch
:
int
,
neutralized_risk
:
Iterable
[
str
]
=
None
,
risk_model
:
str
=
'short'
,
pre_process
:
Iterable
[
object
]
=
None
,
post_process
:
Iterable
[
object
]
=
None
,
warm_start
:
int
=
0
):
self
.
engine
=
engine
self
.
alpha_model
=
alpha_model
self
.
alpha_factors
=
alpha_factors
self
.
freq
=
freq
self
.
universe
=
universe
self
.
batch
=
batch
self
.
neutralized_risk
=
neutralized_risk
self
.
risk_model
=
risk_model
self
.
pre_process
=
pre_process
self
.
post_process
=
post_process
self
.
warm_start
=
warm_start
class
ModelComposer
(
object
):
def
__init__
(
self
,
alpha_model
:
ModelBase
,
data_meta
:
DataMeta
):
self
.
alpha_model
=
alpha_model
self
.
data_meta
=
data_meta
self
.
models
=
{}
self
.
is_updated
=
False
self
.
sorted_keys
=
None
def
train
(
self
,
ref_date
:
str
):
train_data
=
fetch_train_phase
(
self
.
data_meta
.
engine
,
self
.
data_meta
.
alpha_factors
,
ref_date
,
self
.
data_meta
.
freq
,
self
.
data_meta
.
universe
,
self
.
data_meta
.
batch
,
self
.
data_meta
.
neutralized_risk
,
self
.
data_meta
.
risk_model
,
self
.
data_meta
.
pre_process
,
self
.
data_meta
.
post_process
,
self
.
data_meta
.
warm_start
)
x_values
=
train_data
[
'train'
][
'x'
]
y_values
=
train_data
[
'train'
][
'y'
]
self
.
alpha_model
.
fit
(
x_values
,
y_values
)
self
.
models
[
ref_date
]
=
copy
.
deepcopy
(
self
.
alpha_model
)
self
.
is_updated
=
False
def
predict
(
self
,
ref_date
:
str
,
x
:
pd
.
DataFrame
=
None
)
->
pd
.
DataFrame
:
if
x
is
None
:
predict_data
=
fetch_predict_phase
(
self
.
data_meta
.
engine
,
self
.
data_meta
.
alpha_factors
,
ref_date
,
self
.
data_meta
.
freq
,
self
.
data_meta
.
universe
,
self
.
data_meta
.
batch
,
self
.
data_meta
.
neutralized_risk
,
self
.
data_meta
.
risk_model
,
self
.
data_meta
.
pre_process
,
self
.
data_meta
.
post_process
,
self
.
data_meta
.
warm_start
)
x_values
=
predict_data
[
'predict'
][
'x'
]
codes
=
predict_data
[
'predict'
][
'code'
]
else
:
x_values
=
x
.
values
codes
=
x
.
index
model
=
self
.
_fetch_latest_model
(
ref_date
)
return
pd
.
DataFrame
(
model
.
predict
(
x_values
)
.
flatten
(),
index
=
codes
)
def
_fetch_latest_model
(
self
,
ref_date
)
->
ModelBase
:
if
self
.
is_updated
:
sorted_keys
=
self
.
sorted_keys
else
:
sorted_keys
=
sorted
(
self
.
models
.
keys
())
self
.
sorted_keys
=
sorted_keys
self
.
is_updated
=
True
latest_index
=
bisect
.
bisect_left
(
sorted_keys
,
ref_date
)
-
1
return
self
.
models
[
sorted_keys
[
latest_index
]]
if
__name__
==
'__main__'
:
import
numpy
as
np
from
alphamind.data.standardize
import
standardize
from
alphamind.data.winsorize
import
winsorize_normal
from
alphamind.data.engines.sqlengine
import
industry_styles
from
alphamind.data.engines.sqlengine
import
SqlEngine
from
alphamind.model.linearmodel
import
ConstLinearModel
engine
=
SqlEngine
()
alpha_model
=
ConstLinearModel
([
'EPS'
],
np
.
array
([
1.
]))
alpha_factors
=
[
'EPS'
]
freq
=
'1w'
universe
=
Universe
(
'zz500'
,
[
'zz500'
])
batch
=
4
neutralized_risk
=
[
'SIZE'
]
+
industry_styles
risk_model
=
'short'
pre_process
=
[
winsorize_normal
,
standardize
]
pos_process
=
[
winsorize_normal
,
standardize
]
data_meta
=
DataMeta
(
engine
,
alpha_factors
,
freq
,
universe
,
batch
,
neutralized_risk
,
risk_model
,
pre_process
,
pos_process
)
composer
=
ModelComposer
(
alpha_model
,
data_meta
)
composer
.
train
(
'2017-09-20'
)
composer
.
train
(
'2017-09-22'
)
composer
.
train
(
'2017-09-25'
)
composer
.
predict
(
'2017-09-21'
)
alphamind/model/data_preparing.py
View file @
c8079091
...
...
@@ -189,7 +189,7 @@ def fetch_data_package(engine: SqlEngine,
neutralized_risk
:
Iterable
[
str
]
=
None
,
risk_model
:
str
=
'short'
,
pre_process
:
Iterable
[
object
]
=
None
,
post_process
:
Iterable
[
object
]
=
None
):
post_process
:
Iterable
[
object
]
=
None
)
->
dict
:
alpha_logger
.
info
(
"Starting data package fetching ..."
)
transformer
=
Transformer
(
alpha_factors
)
...
...
@@ -243,7 +243,7 @@ def fetch_train_phase(engine,
risk_model
:
str
=
'short'
,
pre_process
:
Iterable
[
object
]
=
None
,
post_process
:
Iterable
[
object
]
=
None
,
warm_start
:
int
=
0
):
warm_start
:
int
=
0
)
->
dict
:
transformer
=
Transformer
(
alpha_factors
)
p
=
Period
(
frequency
)
...
...
alphamind/portfolio/rankbuilder.py
View file @
c8079091
...
...
@@ -12,7 +12,12 @@ from alphamind.utilities import groupby
from
alphamind.utilities
import
set_value
def
rank_build
(
er
:
np
.
ndarray
,
use_rank
:
int
,
groups
:
np
.
ndarray
=
None
)
->
np
.
ndarray
:
def
rank_build
(
er
:
np
.
ndarray
,
use_rank
:
int
,
groups
:
np
.
ndarray
=
None
,
masks
:
np
.
ndarray
=
None
)
->
np
.
ndarray
:
er
=
er
.
copy
()
if
masks
is
not
None
:
er
[
~
masks
]
=
-
np
.
inf
if
er
.
ndim
==
1
or
(
er
.
shape
[
0
]
==
1
or
er
.
shape
[
1
]
==
1
):
# fast path methods for single column er
...
...
alphamind/strategy/sample_strategy.json
View file @
c8079091
...
...
@@ -8,13 +8,20 @@
"post_process"
:
[
"winsorize"
,
"standardize"
]
},
"risk_model"
:
"short"
,
"alpha_model"
:
"LinearRegression"
,
"features"
:
[
"EPS"
,
"ROEDiluted"
],
"risk_model"
:
{
"type"
:
"short"
,
"neutralize_risk"
:
[
"SIZE"
,
"industry_styles"
]
},
"
parameters
"
:
"
alpha_model
"
:
{
"fit_intercept"
:
false
"model_type"
:
"LinearRegression"
,
"features"
:
[
"EPS"
,
"ROEDiluted"
],
"parameters"
:
{
"fit_intercept"
:
false
}
},
"freq"
:
"1d"
,
...
...
@@ -25,7 +32,12 @@
"optimizer"
:
{
"
build_
type"
:
"risk_neutral"
,
"type"
:
"risk_neutral"
,
"neutralize_risk"
:
[
"SIZE"
,
"industry_styles"
]
},
"executor"
:
{
"type"
:
"naive"
}
}
\ No newline at end of file
alphamind/tests/execution/__init__.py
0 → 100644
View file @
c8079091
alphamind/tests/execution/test_naiveexecutor.py
0 → 100644
View file @
c8079091
# -*- coding: utf-8 -*-
"""
Created on 2017-9-22
@author: cheng.li
"""
import
unittest
import
pandas
as
pd
from
alphamind.execution.naiveexecutor
import
NaiveExecutor
class
TestNaiveExecutor
(
unittest
.
TestCase
):
def
test_naive_executor
(
self
):
target_pos
=
pd
.
DataFrame
({
'code'
:
[
1
,
2
,
3
],
'weight'
:
[
0.2
,
0.3
,
0.5
],
'industry'
:
[
'a'
,
'b'
,
'c'
]})
# 1st round
executor
=
NaiveExecutor
()
turn_over
,
executed_pos
=
executor
.
execute
(
target_pos
)
executor
.
set_current
(
executed_pos
)
self
.
assertAlmostEqual
(
turn_over
,
1.0
)
# 2nd round
target_pos
=
pd
.
DataFrame
({
'code'
:
[
1
,
2
,
4
],
'weight'
:
[
0.3
,
0.2
,
0.5
],
'industry'
:
[
'a'
,
'b'
,
'd'
]})
turn_over
,
executed_pos
=
executor
.
execute
(
target_pos
)
executor
.
set_current
(
executed_pos
)
self
.
assertAlmostEqual
(
turn_over
,
1.2
)
# 3rd round
target_pos
=
pd
.
DataFrame
({
'code'
:
[
1
,
3
,
4
],
'weight'
:
[
0.3
,
0.2
,
0.5
],
'industry'
:
[
'a'
,
'c'
,
'd'
]})
turn_over
,
executed_pos
=
executor
.
execute
(
target_pos
)
executor
.
set_current
(
executed_pos
)
self
.
assertAlmostEqual
(
turn_over
,
0.4
)
if
__name__
==
'__main__'
:
unittest
.
main
()
\ No newline at end of file
alphamind/tests/execution/test_pipeline.py
0 → 100644
View file @
c8079091
# -*- coding: utf-8 -*-
"""
Created on 2017-9-25
@author: cheng.li
"""
import
unittest
from
collections
import
deque
import
numpy
as
np
import
pandas
as
pd
from
alphamind.execution.pipeline
import
ExecutionPipeline
from
alphamind.execution.thresholdexecutor
import
ThresholdExecutor
from
alphamind.execution.targetvolexecutor
import
TargetVolExecutor
class
TestExecutionPipelin
(
unittest
.
TestCase
):
def
test_execution_pipeline
(
self
):
n
=
100
window
=
60
target_vol
=
0.01
turn_over_threshold
=
0.5
executor1
=
TargetVolExecutor
(
window
=
window
,
target_vol
=
target_vol
)
executor2
=
ThresholdExecutor
(
turn_over_threshold
=
turn_over_threshold
)
execution_pipeline
=
ExecutionPipeline
(
executors
=
[
executor1
,
executor2
])
return_1
=
np
.
random
.
randn
(
2000
,
n
)
*
0.05
return_2
=
np
.
random
.
randn
(
2000
,
n
)
*
0.2
return_total
=
np
.
concatenate
((
return_1
,
return_2
))
codes
=
np
.
array
(
list
(
range
(
n
)))
ret_deq
=
deque
(
maxlen
=
window
)
for
i
,
row
in
enumerate
(
return_total
):
weights
=
np
.
random
.
randint
(
0
,
100
,
n
)
weights
=
weights
/
weights
.
sum
()
pos
=
pd
.
DataFrame
({
'code'
:
codes
,
'weight'
:
weights
})
turn_over
,
executed_pos
=
execution_pipeline
.
execute
(
pos
)
daily_return
=
row
@
executed_pos
.
weight
.
values
.
flatten
()
data_dict
=
{
'return'
:
daily_return
}
execution_pipeline
.
update
(
data_dict
=
data_dict
)
ret_deq
.
append
(
daily_return
)
alphamind/tests/execution/test_targetvolexecutor.py
0 → 100644
View file @
c8079091
# -*- coding: utf-8 -*-
"""
Created on 2017-9-22
@author: cheng.li
"""
import
unittest
from
collections
import
deque
import
numpy
as
np
import
pandas
as
pd
from
alphamind.execution.targetvolexecutor
import
TargetVolExecutor
class
TestTargetVolExecutor
(
unittest
.
TestCase
):
def
test_target_vol_executor
(
self
):
n
=
100
window
=
30
target_vol
=
0.01
executor
=
TargetVolExecutor
(
window
=
window
,
target_vol
=
target_vol
)
return_1
=
np
.
random
.
randn
(
2000
,
n
)
*
0.05
return_2
=
np
.
random
.
randn
(
2000
,
n
)
*
0.2
return_total
=
np
.
concatenate
((
return_1
,
return_2
))
weights
=
np
.
ones
(
n
)
/
n
codes
=
np
.
array
(
list
(
range
(
n
)))
ret_deq
=
deque
(
maxlen
=
window
)
for
i
,
row
in
enumerate
(
return_total
):
pos
=
pd
.
DataFrame
({
'code'
:
codes
,
'weight'
:
weights
})
turn_over
,
executed_pos
=
executor
.
execute
(
pos
)
if
i
>=
window
:
c_vol
=
np
.
std
(
ret_deq
,
ddof
=
1
)
executed_pos
.
equals
(
pos
*
target_vol
/
c_vol
)
else
:
executed_pos
.
equals
(
pos
)
executor
.
set_current
(
executed_pos
)
daily_return
=
row
@
weights
data_dict
=
{
'return'
:
daily_return
}
executor
.
update
(
data_dict
=
data_dict
)
ret_deq
.
append
(
daily_return
)
if
__name__
==
'__main__'
:
unittest
.
main
()
\ No newline at end of file
alphamind/tests/execution/test_thresholdexecutor.py
0 → 100644
View file @
c8079091
# -*- coding: utf-8 -*-
"""
Created on 2017-9-22
@author: cheng.li
"""
import
unittest
import
pandas
as
pd
from
alphamind.execution.thresholdexecutor
import
ThresholdExecutor
class
TestThresholdExecutor
(
unittest
.
TestCase
):
def
test_threshold_executor
(
self
):
target_pos
=
pd
.
DataFrame
({
'code'
:
[
1
,
2
,
3
],
'weight'
:
[
0.2
,
0.3
,
0.5
],
'industry'
:
[
'a'
,
'b'
,
'c'
]})
executor
=
ThresholdExecutor
(
turn_over_threshold
=
0.5
)
# 1st round
turn_over
,
executed_pos
=
executor
.
execute
(
target_pos
)
executor
.
set_current
(
executed_pos
)
self
.
assertTrue
(
target_pos
.
equals
(
executed_pos
))
self
.
assertAlmostEqual
(
turn_over
,
target_pos
.
weight
.
sum
())
# 2nd round
target_pos
=
pd
.
DataFrame
({
'code'
:
[
1
,
2
,
4
],
'weight'
:
[
0.3
,
0.2
,
0.5
],
'industry'
:
[
'a'
,
'b'
,
'd'
]})
turn_over
,
executed_pos
=
executor
.
execute
(
target_pos
)
executor
.
set_current
(
executed_pos
)
self
.
assertTrue
(
target_pos
.
equals
(
executed_pos
))
self
.
assertTrue
(
executed_pos
.
equals
(
executor
.
current_pos
))
self
.
assertAlmostEqual
(
turn_over
,
1.2
)
# 3rd round
target_pos
=
pd
.
DataFrame
({
'code'
:
[
1
,
3
,
4
],
'weight'
:
[
0.3
,
0.2
,
0.5
],
'industry'
:
[
'a'
,
'c'
,
'd'
]})
turn_over
,
executed_pos2
=
executor
.
execute
(
target_pos
)
executor
.
set_current
(
executed_pos2
)
self
.
assertTrue
(
executed_pos
.
equals
(
executed_pos2
))
self
.
assertAlmostEqual
(
turn_over
,
0.
)
if
__name__
==
'__main__'
:
unittest
.
main
()
alphamind/tests/portfolio/test_rankbuild.py
View file @
c8079091
...
...
@@ -18,6 +18,7 @@ class TestRankBuild(unittest.TestCase):
self
.
n_included
=
300
self
.
n_groups
=
30
self
.
n_portfolio
=
range
(
1
,
10
)
self
.
n_mask
=
100
def
test_rank_build
(
self
):
for
n_portfolio
in
self
.
n_portfolio
:
...
...
@@ -26,10 +27,10 @@ class TestRankBuild(unittest.TestCase):
calc_weights
=
rank_build
(
x
,
self
.
n_included
)
expected_weights
=
np
.
zeros
((
len
(
x
),
n_portfolio
))
masks
=
(
-
x
)
.
argsort
(
axis
=
0
)
.
argsort
(
axis
=
0
)
<
self
.
n_included
chosen
=
(
-
x
)
.
argsort
(
axis
=
0
)
.
argsort
(
axis
=
0
)
<
self
.
n_included
for
j
in
range
(
x
.
shape
[
1
]):
expected_weights
[
masks
[:,
j
],
j
]
=
1.
expected_weights
[
chosen
[:,
j
],
j
]
=
1.
np
.
testing
.
assert_array_almost_equal
(
calc_weights
,
expected_weights
)
...
...
@@ -45,9 +46,32 @@ class TestRankBuild(unittest.TestCase):
grouped_ordering
=
pd
.
DataFrame
(
-
x
)
.
groupby
(
groups
)
.
rank
()
expected_weights
=
np
.
zeros
((
len
(
x
),
n_portfolio
))
masks
=
(
grouped_ordering
<=
n_include
)
.
values
chosen
=
(
grouped_ordering
<=
n_include
)
.
values
for
j
in
range
(
x
.
shape
[
1
]):
expected_weights
[
masks
[:,
j
],
j
]
=
1.
expected_weights
[
chosen
[:,
j
],
j
]
=
1.
np
.
testing
.
assert_array_almost_equal
(
calc_weights
,
expected_weights
)
def
test_rank_build_with_masks
(
self
):
for
n_portfolio
in
self
.
n_portfolio
:
x
=
np
.
random
.
randn
(
self
.
n_samples
,
n_portfolio
)
choices
=
np
.
random
.
choice
(
self
.
n_samples
,
self
.
n_mask
,
replace
=
False
)
masks
=
np
.
full
(
self
.
n_samples
,
True
,
dtype
=
bool
)
masks
[
choices
]
=
False
calc_weights
=
rank_build
(
x
,
self
.
n_included
,
masks
=
masks
)
expected_weights
=
np
.
zeros
((
len
(
x
),
n_portfolio
))
filtered_index
=
np
.
arange
(
len
(
x
))[
masks
]
filtered_x
=
x
[
masks
]
big_boolen
=
np
.
full
(
x
.
shape
,
False
,
dtype
=
bool
)
chosen
=
(
-
filtered_x
)
.
argsort
(
axis
=
0
)
.
argsort
(
axis
=
0
)
<
self
.
n_included
big_boolen
[
filtered_index
]
=
chosen
for
j
in
range
(
x
.
shape
[
1
]):
expected_weights
[
big_boolen
[:,
j
],
j
]
=
1.
np
.
testing
.
assert_array_almost_equal
(
calc_weights
,
expected_weights
)
...
...
alphamind/tests/test_suite.py
View file @
c8079091
...
...
@@ -28,6 +28,9 @@ from alphamind.tests.analysis.test_factoranalysis import TestFactorAnalysis
from
alphamind.tests.analysis.test_quantilieanalysis
import
TestQuantileAnalysis
from
alphamind.tests.model.test_linearmodel
import
TestLinearModel
from
alphamind.tests.model.test_loader
import
TestLoader
from
alphamind.tests.execution.test_naiveexecutor
import
TestNaiveExecutor
from
alphamind.tests.execution.test_thresholdexecutor
import
TestThresholdExecutor
from
alphamind.tests.execution.test_targetvolexecutor
import
TestTargetVolExecutor
if
__name__
==
'__main__'
:
...
...
@@ -47,6 +50,9 @@ if __name__ == '__main__':
TestFactorAnalysis
,
TestQuantileAnalysis
,
TestLinearModel
,
TestLoader
],
TestLoader
,
TestNaiveExecutor
,
TestThresholdExecutor
,
TestTargetVolExecutor
],
alpha_logger
)
runner
.
run
()
notebooks/executor_example.ipynb
0 → 100644
View file @
c8079091
This diff is collapsed.
Click to expand it.
scripts/create_view.sql
View file @
c8079091
...
...
@@ -42,4 +42,4 @@ u."AccountsPayablesTDays",u."AccountsPayablesTRate",u."AdminiExpenseRate",u."ART
left
join
tiny
as
t
on
m
.
trade_date
=
t
.
trade_date
and
m
.
code
=
t
.
code
left
join
experimental
as
e
on
m
.
trade_date
=
e
.
trade_date
and
m
.
code
=
e
.
code
;
create
UNIQUE
index
on
full_factor_view
(
trade_date
,
code
)
\ No newline at end of file
create
UNIQUE
index
on
full_factor_view
(
trade_date
,
code
);
\ No newline at end of file
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