Commit 6b3f0a38 authored by Dr.李's avatar Dr.李

added risk model

parent bce4c53e
...@@ -11,6 +11,9 @@ from typing import Tuple ...@@ -11,6 +11,9 @@ from typing import Tuple
from typing import Optional from typing import Optional
from alphamind.cython.optimizers import QPOptimizer from alphamind.cython.optimizers import QPOptimizer
from alphamind.cython.optimizers import CVOptimizer from alphamind.cython.optimizers import CVOptimizer
from alphamind.portfolio.riskmodel import RiskModel
from alphamind.portfolio.riskmodel import FullRiskModel
from alphamind.portfolio.riskmodel import FactorRiskModel
def _create_bounds(lbound, def _create_bounds(lbound,
...@@ -45,18 +48,30 @@ def _create_result(optimizer, bm): ...@@ -45,18 +48,30 @@ def _create_result(optimizer, bm):
def mean_variance_builder(er: np.ndarray, def mean_variance_builder(er: np.ndarray,
cov: np.ndarray, risk_model: RiskModel,
bm: np.ndarray, bm: np.ndarray,
lbound: Union[np.ndarray, float], lbound: Union[np.ndarray, float],
ubound: Union[np.ndarray, float], ubound: Union[np.ndarray, float],
risk_exposure: Optional[np.ndarray], risk_exposure: Optional[np.ndarray],
risk_target: Optional[Tuple[np.ndarray, np.ndarray]], risk_target: Optional[Tuple[np.ndarray, np.ndarray]],
lam: float=1., lam: float=1.) -> Tuple[str, float, np.ndarray]:
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) lbound, ubound, cons_mat, clbound, cubound = _create_bounds(lbound, ubound, bm, risk_exposure, risk_target)
if isinstance(risk_model, FullRiskModel):
cov = risk_model.get_cov()
optimizer = QPOptimizer(er,
cov,
lbound,
ubound,
cons_mat,
clbound,
cubound,
lam)
elif isinstance(risk_model, FactorRiskModel):
cov = None
factor_cov = risk_model.get_factor_cov()
factor_loading = risk_model.get_risk_exp()
idsync = risk_model.get_idsync()
optimizer = QPOptimizer(er, optimizer = QPOptimizer(er,
cov, cov,
lbound, lbound,
...@@ -68,24 +83,24 @@ def mean_variance_builder(er: np.ndarray, ...@@ -68,24 +83,24 @@ def mean_variance_builder(er: np.ndarray,
factor_cov, factor_cov,
factor_loading, factor_loading,
idsync) idsync)
else:
raise ValueError("{0} is not recognized as valid risk model".format(risk_model))
return _create_result(optimizer, bm) return _create_result(optimizer, bm)
def target_vol_builder(er: np.ndarray, def target_vol_builder(er: np.ndarray,
cov: np.ndarray, risk_model: RiskModel,
bm: np.ndarray, bm: np.ndarray,
lbound: Union[np.ndarray, float], lbound: Union[np.ndarray, float],
ubound: Union[np.ndarray, float], ubound: Union[np.ndarray, float],
risk_exposure: Optional[np.ndarray], risk_exposure: Optional[np.ndarray],
risk_target: Optional[Tuple[np.ndarray, np.ndarray]], risk_target: Optional[Tuple[np.ndarray, np.ndarray]],
vol_low: float = 0., vol_target: 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) lbound, ubound, cons_mat, clbound, cubound = _create_bounds(lbound, ubound, bm, risk_exposure, risk_target)
if isinstance(risk_model, FullRiskModel):
cov = risk_model.get_cov()
optimizer = CVOptimizer(er, optimizer = CVOptimizer(er,
cov, cov,
lbound, lbound,
...@@ -93,11 +108,27 @@ def target_vol_builder(er: np.ndarray, ...@@ -93,11 +108,27 @@ def target_vol_builder(er: np.ndarray,
cons_mat, cons_mat,
clbound, clbound,
cubound, cubound,
vol_low, 0.,
vol_high, vol_target)
elif isinstance(risk_model, FactorRiskModel):
cov = None
factor_cov = risk_model.get_factor_cov()
factor_loading = risk_model.get_risk_exp()
idsync = risk_model.get_idsync()
optimizer = CVOptimizer(er,
cov,
lbound,
ubound,
cons_mat,
clbound,
cubound,
0.,
vol_target,
factor_cov, factor_cov,
factor_loading, factor_loading,
idsync) idsync)
else:
raise ValueError("{0} is not recognized as valid risk model".format(risk_model))
return _create_result(optimizer, bm) return _create_result(optimizer, bm)
......
# -*- coding: utf-8 -*-
"""
Created on 2018-5-29
@author: cheng.li
"""
import abc
from typing import List
import pandas as pd
class RiskModel(metaclass=abc.ABCMeta):
pass
class FullRiskModel(RiskModel):
def __init__(self, sec_cov: pd.DataFrame):
self.codes = sec_cov.index.tolist()
self.sec_cov = sec_cov.loc[self.codes, self.codes]
def get_cov(self, codes: List[int]=None):
if codes:
return self.sec_cov.loc[codes, codes].values
else:
return self.sec_cov.values
class FactorRiskModel(RiskModel):
def __init__(self,
factor_cov: pd.DataFrame,
risk_exp: pd.DataFrame,
idsync: pd.Series):
self.factor_cov = factor_cov
self.idsync = idsync
self.codes = self.idsync.index.tolist()
self.factor_names = sorted(self.factor_cov.index)
self.risk_exp = risk_exp.loc[self.codes, self.factor_names]
self.factor_cov = self.factor_cov.loc[self.factor_names, self.factor_names]
self.idsync = self.idsync[self.codes]
def get_risk_exp(self, codes: List[int]=None):
if codes:
return self.risk_exp.loc[codes, :].values
else:
return self.risk_exp.values
def get_factor_cov(self):
return self.factor_cov.values
def get_idsync(self, codes: List[int]=None):
if codes:
return self.idsync[codes].values
else:
return self.idsync.values
\ No newline at end of file
...@@ -7,6 +7,8 @@ Created on 2017-6-27 ...@@ -7,6 +7,8 @@ Created on 2017-6-27
import unittest import unittest
import numpy as np import numpy as np
import pandas as pd
from alphamind.portfolio.riskmodel import FullRiskModel
from alphamind.portfolio.meanvariancebuilder import mean_variance_builder from alphamind.portfolio.meanvariancebuilder import mean_variance_builder
from alphamind.portfolio.meanvariancebuilder import target_vol_builder from alphamind.portfolio.meanvariancebuilder import target_vol_builder
...@@ -29,7 +31,8 @@ class TestMeanVarianceBuild(unittest.TestCase): ...@@ -29,7 +31,8 @@ class TestMeanVarianceBuild(unittest.TestCase):
[1., 0., 1.]]).T [1., 0., 1.]]).T
risk_target = (np.array([bm.sum(), 0.3]), np.array([bm.sum(), 0.7])) risk_target = (np.array([bm.sum(), 0.3]), np.array([bm.sum(), 0.7]))
status, _, x = mean_variance_builder(er, cov, bm, lbound, ubound, risk_exposure, risk_target) model = FullRiskModel(pd.DataFrame(cov))
status, _, x = mean_variance_builder(er, model, bm, lbound, ubound, risk_exposure, risk_target)
self.assertTrue(status == 'optimal') self.assertTrue(status == 'optimal')
self.assertAlmostEqual(x.sum(), bm.sum()) self.assertAlmostEqual(x.sum(), bm.sum())
...@@ -55,7 +58,8 @@ class TestMeanVarianceBuild(unittest.TestCase): ...@@ -55,7 +58,8 @@ class TestMeanVarianceBuild(unittest.TestCase):
[1., 0., 1.]]).T [1., 0., 1.]]).T
risk_target = (np.array([bm.sum(), 0.3]), np.array([bm.sum(), 0.7])) risk_target = (np.array([bm.sum(), 0.3]), np.array([bm.sum(), 0.7]))
status, _, x = mean_variance_builder(er, cov, bm, lbound, ubound, risk_exposure, risk_target, lam=100) model = FullRiskModel(pd.DataFrame(cov))
status, _, x = mean_variance_builder(er, model, bm, lbound, ubound, risk_exposure, risk_target, lam=100)
self.assertTrue(status == 'optimal') self.assertTrue(status == 'optimal')
self.assertAlmostEqual(x.sum(), bm.sum()) self.assertAlmostEqual(x.sum(), bm.sum())
...@@ -78,7 +82,8 @@ class TestMeanVarianceBuild(unittest.TestCase): ...@@ -78,7 +82,8 @@ class TestMeanVarianceBuild(unittest.TestCase):
risk_exposure = np.array([[1., 1., 1.]]).T risk_exposure = np.array([[1., 1., 1.]]).T
risk_target = (np.array([bm.sum()]), np.array([bm.sum()])) risk_target = (np.array([bm.sum()]), np.array([bm.sum()]))
status, _, x = target_vol_builder(er, cov, bm, lbound, ubound, risk_exposure, risk_target, 0.1, 0.1) model = FullRiskModel(pd.DataFrame(cov))
status, _, x = target_vol_builder(er, model, bm, lbound, ubound, risk_exposure, risk_target, 0.1)
self.assertTrue(status == 'optimal') self.assertTrue(status == 'optimal')
self.assertTrue(np.all(x <= ubound + 1.e-6)) self.assertTrue(np.all(x <= ubound + 1.e-6))
self.assertTrue(np.all(x >= lbound) - 1.e-6) self.assertTrue(np.all(x >= lbound) - 1.e-6)
......
# -*- coding: utf-8 -*-
"""
Created on 2018-5-29
@author: cheng.li
"""
import unittest
import numpy as np
import pandas as pd
from alphamind.portfolio.riskmodel import FullRiskModel
from alphamind.portfolio.riskmodel import FactorRiskModel
class TestRiskModel(unittest.TestCase):
def setUp(self):
self.factor_cov = pd.DataFrame([[0.5, -0.3], [-0.3, 0.7]], columns=['a', 'b'], index=['a', 'b'])
self.risk_exp = pd.DataFrame([[0.8, 0.2], [0.5, 0.5], [0.2, 0.8]], columns=['a', 'b'], index=[1, 2, 3])
self.idsync = pd.Series([0.1, 0.3, 0.2], index=[1, 2, 3])
self.sec_cov = self.risk_exp.values @ self.factor_cov.values @ self.risk_exp.values.T \
+ np.diag(self.idsync.values)
self.sec_cov = pd.DataFrame(self.sec_cov, columns=[1, 2, 3], index=[1, 2, 3])
def test_full_risk_model(self):
self.assertEqual(self.sec_cov.shape, (3, 3))
model = FullRiskModel(self.sec_cov)
codes = [1, 2]
res = model.get_cov(codes)
np.testing.assert_array_almost_equal(res, self.sec_cov.loc[codes, codes].values)
res = model.get_cov()
np.testing.assert_array_almost_equal(res, self.sec_cov.values)
def test_factor_risk_model(self):
self.assertEqual(self.factor_cov.shape, (2, 2))
self.assertEqual(self.risk_exp.shape, (3, 2))
self.assertEqual(self.idsync.shape, (3,))
model = FactorRiskModel(self.factor_cov,
self.risk_exp,
self.idsync)
res = model.get_factor_cov()
np.testing.assert_array_almost_equal(res, self.factor_cov.values)
codes = [1, 3]
res = model.get_risk_exp(codes)
np.testing.assert_array_almost_equal(res, self.risk_exp.loc[codes, :])
res = model.get_idsync(codes)
np.testing.assert_array_almost_equal(res, self.idsync[codes])
res = model.get_risk_exp()
np.testing.assert_array_almost_equal(res, self.risk_exp)
res = model.get_idsync()
np.testing.assert_array_almost_equal(res, self.idsync)
...@@ -35,6 +35,7 @@ if __name__ == '__main__': ...@@ -35,6 +35,7 @@ if __name__ == '__main__':
from alphamind.tests.portfolio.test_percentbuild import TestPercentBuild from alphamind.tests.portfolio.test_percentbuild import TestPercentBuild
from alphamind.tests.portfolio.test_linearbuild import TestLinearBuild from alphamind.tests.portfolio.test_linearbuild import TestLinearBuild
from alphamind.tests.portfolio.test_meanvariancebuild import TestMeanVarianceBuild from alphamind.tests.portfolio.test_meanvariancebuild import TestMeanVarianceBuild
from alphamind.tests.portfolio.test_riskmodel import TestRiskModel
from alphamind.tests.settlement.test_simplesettle import TestSimpleSettle from alphamind.tests.settlement.test_simplesettle import TestSimpleSettle
from alphamind.tests.analysis.test_riskanalysis import TestRiskAnalysis from alphamind.tests.analysis.test_riskanalysis import TestRiskAnalysis
from alphamind.tests.analysis.test_perfanalysis import TestPerformanceAnalysis from alphamind.tests.analysis.test_perfanalysis import TestPerformanceAnalysis
...@@ -64,6 +65,7 @@ if __name__ == '__main__': ...@@ -64,6 +65,7 @@ if __name__ == '__main__':
TestPercentBuild, TestPercentBuild,
TestLinearBuild, TestLinearBuild,
TestMeanVarianceBuild, TestMeanVarianceBuild,
TestRiskModel,
TestSimpleSettle, TestSimpleSettle,
TestRiskAnalysis, TestRiskAnalysis,
TestPerformanceAnalysis, TestPerformanceAnalysis,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment