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

added risk model

parent bce4c53e
......@@ -11,6 +11,9 @@ from typing import Tuple
from typing import Optional
from alphamind.cython.optimizers import QPOptimizer
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,
......@@ -45,59 +48,87 @@ def _create_result(optimizer, bm):
def mean_variance_builder(er: np.ndarray,
cov: np.ndarray,
risk_model: RiskModel,
bm: np.ndarray,
lbound: Union[np.ndarray, float],
ubound: Union[np.ndarray, float],
risk_exposure: Optional[np.ndarray],
risk_target: Optional[Tuple[np.ndarray, np.ndarray]],
lam: float=1.,
factor_cov: np.ndarray=None,
factor_loading: np.ndarray=None,
idsync: np.ndarray=None) -> Tuple[str, float, np.ndarray]:
lam: float=1.) -> Tuple[str, float, np.ndarray]:
lbound, ubound, cons_mat, clbound, cubound = _create_bounds(lbound, ubound, bm, risk_exposure, risk_target)
optimizer = QPOptimizer(er,
cov,
lbound,
ubound,
cons_mat,
clbound,
cubound,
lam,
factor_cov,
factor_loading,
idsync)
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,
cov,
lbound,
ubound,
cons_mat,
clbound,
cubound,
lam,
factor_cov,
factor_loading,
idsync)
else:
raise ValueError("{0} is not recognized as valid risk model".format(risk_model))
return _create_result(optimizer, bm)
def target_vol_builder(er: np.ndarray,
cov: np.ndarray,
risk_model: RiskModel,
bm: np.ndarray,
lbound: Union[np.ndarray, float],
ubound: Union[np.ndarray, float],
risk_exposure: Optional[np.ndarray],
risk_target: Optional[Tuple[np.ndarray, np.ndarray]],
vol_low: float = 0.,
vol_high: float = 1.,
factor_cov: np.ndarray = None,
factor_loading: np.ndarray = None,
idsync: np.ndarray = None)-> Tuple[str, float, np.ndarray]:
vol_target: float = 1.)-> Tuple[str, float, np.ndarray]:
lbound, ubound, cons_mat, clbound, cubound = _create_bounds(lbound, ubound, bm, risk_exposure, risk_target)
optimizer = CVOptimizer(er,
cov,
lbound,
ubound,
cons_mat,
clbound,
cubound,
vol_low,
vol_high,
factor_cov,
factor_loading,
idsync)
if isinstance(risk_model, FullRiskModel):
cov = risk_model.get_cov()
optimizer = CVOptimizer(er,
cov,
lbound,
ubound,
cons_mat,
clbound,
cubound,
0.,
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_loading,
idsync)
else:
raise ValueError("{0} is not recognized as valid risk model".format(risk_model))
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
import unittest
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 target_vol_builder
......@@ -29,7 +31,8 @@ class TestMeanVarianceBuild(unittest.TestCase):
[1., 0., 1.]]).T
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.assertAlmostEqual(x.sum(), bm.sum())
......@@ -55,7 +58,8 @@ class TestMeanVarianceBuild(unittest.TestCase):
[1., 0., 1.]]).T
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.assertAlmostEqual(x.sum(), bm.sum())
......@@ -78,7 +82,8 @@ class TestMeanVarianceBuild(unittest.TestCase):
risk_exposure = np.array([[1., 1., 1.]]).T
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(np.all(x <= ubound + 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__':
from alphamind.tests.portfolio.test_percentbuild import TestPercentBuild
from alphamind.tests.portfolio.test_linearbuild import TestLinearBuild
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.analysis.test_riskanalysis import TestRiskAnalysis
from alphamind.tests.analysis.test_perfanalysis import TestPerformanceAnalysis
......@@ -64,6 +65,7 @@ if __name__ == '__main__':
TestPercentBuild,
TestLinearBuild,
TestMeanVarianceBuild,
TestRiskModel,
TestSimpleSettle,
TestRiskAnalysis,
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