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
565be84d
Unverified
Commit
565be84d
authored
May 28, 2018
by
iLampard
Committed by
GitHub
May 28, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14 from alpha-miner/master
merge update
parents
60fe5dca
8541e9e2
Changes
6
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
264 additions
and
77 deletions
+264
-77
optimizers.pyx
alphamind/cython/optimizers.pyx
+80
-49
sqlengine.py
alphamind/data/engines/sqlengine.py
+1
-1
pfopt
alphamind/pfopt
+1
-1
meanvariancebuilder.py
alphamind/portfolio/meanvariancebuilder.py
+16
-4
test_optimizers.py
alphamind/tests/cython/test_optimizers.py
+62
-0
Example 7 - Portfolio Optimizer Performance.ipynb
notebooks/Example 7 - Portfolio Optimizer Performance.ipynb
+104
-22
No files found.
alphamind/cython/optimizers.pyx
View file @
565be84d
...
...
@@ -10,6 +10,7 @@ cimport numpy as cnp
from libcpp.string cimport string
from libcpp.vector cimport vector
import numpy as np
from PyFin.api import pyFinAssert
cdef extern from "lpoptimizer.hpp" namespace "pfopt":
...
...
@@ -71,7 +72,11 @@ cdef extern from "tvoptimizer.hpp" namespace "pfopt":
double*,
double*,
double,
double) except +
double,
int,
double*,
double*,
double*) except +
vector[double] xValue()
double feval()
int status()
...
...
@@ -81,6 +86,7 @@ cdef class CVOptimizer:
cdef TVOptimizer* cobj
cdef int n
cdef int m
cdef int f
def __cinit__(self,
double[:] expected_return,
...
...
@@ -91,20 +97,26 @@ cdef class CVOptimizer:
double[:] clbound=None,
double[:] cubound=None,
double target_low=0.0,
double target_high=1.0):
double target_high=1.0,
cnp.ndarray[double, ndim=2] factor_cov_matrix=None,
cnp.ndarray[double, ndim=2] factor_loading_matrix=None,
double[:] idsync_risk=None):
self.n = lbound.shape[0]
self.m = 0
cdef double[:] cov = cov_matrix.flatten(order='C')
self.f = factor_cov_matrix.shape[0] if factor_cov_matrix is not None else 0
cdef double[:] cov = cov_matrix.flatten(order='C') if cov_matrix is not None else None
cdef double[:] cons
cdef double[:] factor_cov = factor_cov_matrix.flatten(order='C') if factor_cov_matrix is not None else None
cdef double[:] factor_loading = factor_loading_matrix.flatten(order='C') if factor_loading_matrix is not None else None
if cons_matrix is not None:
self.m = cons_matrix.shape[0]
cons = cons_matrix.flatten(order='C')
;
cons = cons_matrix.flatten(order='C')
self.cobj = new TVOptimizer(self.n,
&expected_return[0],
&cov[0],
&cov[0]
if cov is not None else NULL
,
&lbound[0],
&ubound[0],
self.m,
...
...
@@ -112,11 +124,15 @@ cdef class CVOptimizer:
&clbound[0],
&cubound[0],
target_low,
target_high)
target_high,
self.f,
&factor_cov[0] if factor_cov is not None else NULL,
&factor_loading[0] if factor_loading is not None else NULL,
&idsync_risk[0] if idsync_risk is not None else NULL)
else:
self.cobj = new TVOptimizer(self.n,
&expected_return[0],
&cov[0],
&cov[0]
if cov is not None else NULL
,
&lbound[0],
&ubound[0],
0,
...
...
@@ -124,7 +140,11 @@ cdef class CVOptimizer:
NULL,
NULL,
target_low,
target_high)
target_high,
self.f,
&factor_cov[0] if factor_cov is not None else NULL,
&factor_loading[0] if factor_loading is not None else NULL,
&idsync_risk[0] if idsync_risk is not None else NULL)
def __dealloc__(self):
del self.cobj
...
...
@@ -150,7 +170,11 @@ cdef extern from "mvoptimizer.hpp" namespace "pfopt":
double*,
double*,
double*,
double) except +
double,
int,
double*,
double*,
double*) except +
vector[double] xValue()
double feval()
int status()
...
...
@@ -171,12 +195,12 @@ cdef extern from "qpalglib.hpp" namespace "pfopt":
cdef class QPOptimizer:
cdef MVOptimizer* cobj
cdef QPAlglib* cobj2
cdef cnp.ndarray er
cdef cnp.ndarray cov
cdef double risk_aversion
cdef int n
cdef int m
cdef int f
def __cinit__(self,
double[:] expected_return,
...
...
@@ -186,15 +210,21 @@ cdef class QPOptimizer:
cnp.ndarray[double, ndim=2] cons_matrix=None,
double[:] clbound=None,
double[:] cubound=None,
double risk_aversion=1.0):
double risk_aversion=1.0,
cnp.ndarray[double, ndim=2] factor_cov_matrix=None,
cnp.ndarray[double, ndim=2] factor_loading_matrix=None,
double[:] idsync_risk=None):
self.n = lbound.shape[0]
self.m = 0
self.f = factor_cov_matrix.shape[0] if factor_cov_matrix is not None else 0
self.er = np.array(expected_return)
self.cov = np.array(cov_matrix)
self.risk_aversion = risk_aversion
cdef double[:] cov = cov_matrix.flatten(order='C')
cdef double[:] cov = cov_matrix.flatten(order='C')
if cov_matrix is not None else None
cdef double[:] cons
cdef double[:] factor_cov = factor_cov_matrix.flatten(order='C') if factor_cov_matrix is not None else None
cdef double[:] factor_loading = factor_loading_matrix.flatten(order='C') if factor_loading_matrix is not None else None
if cons_matrix is not None:
self.m = cons_matrix.shape[0]
...
...
@@ -202,48 +232,49 @@ cdef class QPOptimizer:
self.cobj = new MVOptimizer(self.n,
&expected_return[0],
&cov[0],
&cov[0]
if cov is not None else NULL
,
&lbound[0],
&ubound[0],
self.m,
&cons[0],
&clbound[0],
&cubound[0],
risk_aversion)
risk_aversion,
self.f,
&factor_cov[0] if factor_cov is not None else NULL,
&factor_loading[0] if factor_loading is not None else NULL,
&idsync_risk[0] if idsync_risk is not None else NULL)
else:
self.cobj2 = new QPAlglib(self.n,
# self.cobj2 = new QPAlglib(self.n,
# &expected_return[0],
# &cov[0] if cov is not None else NULL,
# &lbound[0],
# &ubound[0],
# risk_aversion)
self.cobj = new MVOptimizer(self.n,
&expected_return[0],
&cov[0]
,
&cov[0] if cov is not None else NULL
,
&lbound[0],
&ubound[0],
risk_aversion)
self.m,
NULL,
NULL,
NULL,
risk_aversion,
self.f,
&factor_cov[0] if factor_cov is not None else NULL,
&factor_loading[0] if factor_loading is not None else NULL,
&idsync_risk[0] if idsync_risk is not None else NULL)
def __dealloc__(self):
if self.cobj:
del self.cobj
else:
del self.cobj2
def feval(self):
if self.cobj:
return self.cobj.feval()
else:
x = np.array(self.cobj2.xValue())
return 0.5 * self.risk_aversion * x @ self.cov @ x - self.er @ x
def x_value(self):
if self.cobj:
return np.array(self.cobj.xValue())
else:
return np.array(self.cobj2.xValue())
def status(self):
if self.cobj:
return self.cobj.status()
else:
status = self.cobj2.status()
if 1 <= status <= 4:
return 0
else:
return status
alphamind/data/engines/sqlengine.py
View file @
565be84d
...
...
@@ -371,7 +371,7 @@ class SqlEngine(object):
res
[
'chgPct'
]
=
df
.
chgPct
res
=
res
.
loc
[
ref_date
]
res
.
index
=
list
(
range
(
len
(
res
)))
return
res
.
drop_duplicates
([
'trade_date'
,
'code'
])
return
res
def
fetch_factor_range
(
self
,
universe
:
Universe
,
...
...
pfopt
@
40976afd
Subproject commit
1dcecd88728512ff50730f418d9d58195bf33851
Subproject commit
40976afd3ea03b921177cef364fa8a6b37bf4dda
alphamind/portfolio/meanvariancebuilder.py
View file @
565be84d
...
...
@@ -51,7 +51,10 @@ def mean_variance_builder(er: np.ndarray,
ubound
:
Union
[
np
.
ndarray
,
float
],
risk_exposure
:
Optional
[
np
.
ndarray
],
risk_target
:
Optional
[
Tuple
[
np
.
ndarray
,
np
.
ndarray
]],
lam
:
float
=
1.
)
->
Tuple
[
str
,
float
,
np
.
ndarray
]:
lam
:
float
=
1.
,
factor_cov
:
np
.
ndarray
=
None
,
factor_loading
:
np
.
ndarray
=
None
,
idsync
:
np
.
ndarray
=
None
)
->
Tuple
[
str
,
float
,
np
.
ndarray
]:
lbound
,
ubound
,
cons_mat
,
clbound
,
cubound
=
_create_bounds
(
lbound
,
ubound
,
bm
,
risk_exposure
,
risk_target
)
optimizer
=
QPOptimizer
(
er
,
...
...
@@ -61,7 +64,10 @@ def mean_variance_builder(er: np.ndarray,
cons_mat
,
clbound
,
cubound
,
lam
)
lam
,
factor_cov
,
factor_loading
,
idsync
)
return
_create_result
(
optimizer
,
bm
)
...
...
@@ -74,7 +80,10 @@ def target_vol_builder(er: np.ndarray,
risk_exposure
:
Optional
[
np
.
ndarray
],
risk_target
:
Optional
[
Tuple
[
np
.
ndarray
,
np
.
ndarray
]],
vol_low
:
float
=
0.
,
vol_high
:
float
=
1.
)
->
Tuple
[
str
,
float
,
np
.
ndarray
]:
vol_high
:
float
=
1.
,
factor_cov
:
np
.
ndarray
=
None
,
factor_loading
:
np
.
ndarray
=
None
,
idsync
:
np
.
ndarray
=
None
)
->
Tuple
[
str
,
float
,
np
.
ndarray
]:
lbound
,
ubound
,
cons_mat
,
clbound
,
cubound
=
_create_bounds
(
lbound
,
ubound
,
bm
,
risk_exposure
,
risk_target
)
optimizer
=
CVOptimizer
(
er
,
...
...
@@ -85,7 +94,10 @@ def target_vol_builder(er: np.ndarray,
clbound
,
cubound
,
vol_low
,
vol_high
)
vol_high
,
factor_cov
,
factor_loading
,
idsync
)
return
_create_result
(
optimizer
,
bm
)
...
...
alphamind/tests/cython/test_optimizers.py
View file @
565be84d
...
...
@@ -54,6 +54,36 @@ class TestOptimizers(unittest.TestCase):
[
0.1996
,
0.3004
,
0.5000
],
4
)
def
test_qpoptimizer_with_factor_model
(
self
):
objective
=
np
.
array
([
0.1
,
0.2
,
0.3
])
lbound
=
np
.
array
([
0.0
,
0.0
,
0.0
])
ubound
=
np
.
array
([
1.0
,
1.0
,
1.0
])
factor_var
=
np
.
array
([[
0.5
,
-
0.3
],
[
-
0.3
,
0.7
]])
factor_load
=
np
.
array
([[
0.8
,
0.2
],
[
0.5
,
0.5
],
[
0.2
,
0.8
]])
idsync
=
np
.
array
([
0.1
,
0.3
,
0.2
])
cons
=
np
.
array
([[
1.
,
1.
,
1.
]])
clbound
=
np
.
array
([
1.
])
cubound
=
np
.
array
([
1.
])
optimizer
=
QPOptimizer
(
objective
,
None
,
lbound
,
ubound
,
cons
,
clbound
,
cubound
,
1.
,
factor_var
,
factor_load
,
idsync
)
# check against cvxpy result
np
.
testing
.
assert_array_almost_equal
(
optimizer
.
x_value
(),
[
0.2866857
,
0.21416417
,
0.49915014
],
4
)
def
test_qpoptimizer_with_identity_matrix
(
self
):
objective
=
np
.
array
([
-
0.02
,
0.01
,
0.03
])
cov
=
np
.
diag
([
1.
,
1.
,
1.
])
...
...
@@ -122,6 +152,38 @@ class TestOptimizers(unittest.TestCase):
[
-
0.3
,
-
0.10919033
,
0.40919033
],
4
)
def
test_cvoptimizer_with_factor_model
(
self
):
objective
=
np
.
array
([
0.1
,
0.2
,
0.3
])
lbound
=
np
.
array
([
0.0
,
0.0
,
0.0
])
ubound
=
np
.
array
([
1.0
,
1.0
,
1.0
])
factor_var
=
np
.
array
([[
0.5
,
-
0.3
],
[
-
0.3
,
0.7
]])
factor_load
=
np
.
array
([[
0.8
,
0.2
],
[
0.5
,
0.5
],
[
0.2
,
0.8
]])
idsync
=
np
.
array
([
0.1
,
0.3
,
0.2
])
cons
=
np
.
array
([[
1.
,
1.
,
1.
]])
clbound
=
np
.
array
([
1.
])
cubound
=
np
.
array
([
1.
])
target_vol
=
0.5
optimizer
=
CVOptimizer
(
objective
,
None
,
lbound
,
ubound
,
cons
,
clbound
,
cubound
,
0.
,
target_vol
,
factor_var
,
factor_load
,
idsync
)
# check against cvxpy result
np
.
testing
.
assert_array_almost_equal
(
optimizer
.
x_value
(),
[
0.26595552
,
0.21675092
,
0.51729356
],
4
)
def
test_cvoptimizer_with_cons_and_ieq
(
self
):
objective
=
np
.
array
([
0.1
,
0.2
,
0.3
])
cov
=
np
.
array
([[
0.05
,
0.01
,
0.02
],
...
...
notebooks/Example 7 - Portfolio Optimizer Performance.ipynb
View file @
565be84d
This diff is collapsed.
Click to expand it.
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