Commit 561e1046 authored by Dr.李's avatar Dr.李

update model api

parent eac7bef8
......@@ -43,6 +43,48 @@ class DataMeta(object):
self.warm_start = warm_start
def train_model(ref_date: str,
alpha_model: ModelBase,
data_meta: DataMeta):
train_data = fetch_train_phase(data_meta.engine,
data_meta.alpha_factors,
ref_date,
data_meta.freq,
data_meta.universe,
data_meta.batch,
data_meta.neutralized_risk,
data_meta.risk_model,
data_meta.pre_process,
data_meta.post_process,
data_meta.warm_start)
x_values = train_data['train']['x']
y_values = train_data['train']['y']
alpha_model.fit(x_values, y_values)
return copy.deepcopy(alpha_model)
def predict_by_model(ref_date: str,
alpha_model: ModelBase,
data_meta):
predict_data = fetch_predict_phase(data_meta.engine,
data_meta.alpha_factors,
ref_date,
data_meta.freq,
data_meta.universe,
data_meta.batch,
data_meta.neutralized_risk,
data_meta.risk_model,
data_meta.pre_process,
data_meta.post_process,
data_meta.warm_start)
x_values = predict_data['predict']['x']
codes = predict_data['predict']['code']
return pd.DataFrame(alpha_model.predict(x_values).flatten(), index=codes)
class ModelComposer(object):
def __init__(self,
alpha_model: ModelBase,
......@@ -55,46 +97,16 @@ class ModelComposer(object):
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.models[ref_date] = train_model(ref_date, self.alpha_model, self.data_meta)
self.is_updated = False
def predict(self, ref_date: str, x: pd.DataFrame = None) -> pd.DataFrame:
model = self._fetch_latest_model(ref_date)
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']
return predict_by_model(ref_date, model, self.data_meta)
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:
......
......@@ -12,13 +12,14 @@ import numpy as np
from alphamind.utilities import alpha_logger
from alphamind.utilities import encode
from alphamind.utilities import decode
from alphamind.data.transformer import Transformer
class ModelBase(metaclass=abc.ABCMeta):
def __init__(self, features: list=None, formulas: dict=None):
if features is not None:
self.features = list(features)
self.features = Transformer(features).names
else:
self.features = None
self.impl = None
......
......@@ -16,9 +16,9 @@ class Allocation(object):
def __init__(self,
code: int,
minimum: int=0,
maximum: int=inf,
current: int=0):
minimum: int = 0,
maximum: int = inf,
current: int = 0):
self.code = code
self.minimum = minimum
self.maximum = maximum
......@@ -62,39 +62,32 @@ class Portfolio(object):
class Execution(object):
def __init__(self,
name: str,
code: int,
qty: int,
comment: str=None):
cpty: str = 'external',
comment: str = None):
self.name = name
self.code = code
self.qty = qty
self.cpty = cpty
self.comment = comment
def __repr__(self):
return "Execution(code={0}, qty={1}, comment={2})".format(self.code,
return "Execution(name={0}, code={1}, qty={2}, cpty={3}, comment={4})".format(self.name,
self.code,
self.qty,
self.cpty,
self.comment)
class Executions(object):
def __init__(self,
name,
executions: List[Execution]=None):
self.name = name
self.executions = executions
def __repr__(self):
return "Executions(name={0}, executions={1})".format(self.name,
self.executions)
class Asset(object):
def __init__(self,
code: int,
name: str=None,
priority: List[str]=None,
forbidden: List[str]=None):
name: str = None,
priority: List[str] = None,
forbidden: List[str] = None):
self.code = code
self.name = name
if priority:
......@@ -119,11 +112,11 @@ class Asset(object):
self.forbidden)
class TargetPositions(object):
class Positions(object):
def __init__(self,
assets: List[Asset]=None,
qtys: List[int]=None):
assets: List[Asset] = None,
qtys: List[int] = None):
if assets:
self.targets = {asset.code: (asset, qty) for asset, qty in zip(assets, qtys)}
......@@ -133,9 +126,9 @@ class TargetPositions(object):
def add_asset(self,
asset: Asset,
qty: int):
if asset.code in self.targets:
raise ValueError()
self.targets[asset.code] = (asset, qty)
code = asset.code
pyFinAssert(code not in self.targets, ValueError, "code {0} is already in positions".format(code))
self.targets[code] = (asset, qty)
def __getitem__(self, code: int) -> Tuple[Asset, int]:
return self.targets[code]
......@@ -148,10 +141,10 @@ class TargetPositions(object):
return "TargetPositions(assets={0}, qtys={1})".format(*zip(*self.targets.values()))
def handle_one_asset(pre_allocation: Allocation,
def handle_one_asset(p_name: str,
pre_allocation: Allocation,
asset: Asset,
qty: int) -> Tuple[Execution, Allocation, int]:
minimum = pre_allocation.minimum
maximum = pre_allocation.maximum
current = pre_allocation.current
......@@ -161,14 +154,20 @@ def handle_one_asset(pre_allocation: Allocation,
raise ValueError("{0}'s target {1} is smaller than minimum amount {2}".format(asset.code, qty, pre_allocation))
elif qty < maximum:
# need to buy / sell
ex = Execution(code, qty - current)
ex = Execution(name=p_name,
code=code,
qty=qty - current,
cpty='external')
allocation = Allocation(code,
minimum=minimum,
maximum=maximum,
current=qty)
qty = 0
else:
ex = Execution(code, maximum - current)
ex = Execution(name=p_name,
code=code,
qty=maximum - current,
cpty='external')
allocation = Allocation(code,
minimum=minimum,
maximum=maximum,
......@@ -177,41 +176,40 @@ def handle_one_asset(pre_allocation: Allocation,
return ex, allocation, qty
def pass_through(target_pos: TargetPositions,
portfolio: Portfolio) -> Tuple[Executions, Portfolio, TargetPositions]:
def pass_through(target_pos: Positions,
portfolio: Portfolio) -> Tuple[List[Execution], Portfolio, Positions]:
p_name = portfolio.name
new_target_pos = TargetPositions()
new_target_pos = Positions()
allocations = []
executions = []
for code in target_pos.codes:
asset, qty = target_pos[code]
if asset.priority:
raise ValueError("asset ({0})'s priority pool {1} is not checked yet".format(code, asset.priority))
pyFinAssert(not asset.priority,
ValueError,
"asset ({0})'s priority pool {1} is not checked yet".format(code, asset.priority))
if p_name in asset.forbidden:
ex = Execution(code, 0, "{0} is forbidden for {1}".format(code, p_name))
allocation = copy.deepcopy(portfolio[code])
new_target_pos.add_asset(asset, qty)
else:
prev_allocation = portfolio[code]
ex, allocation, qty = handle_one_asset(prev_allocation, asset, qty)
ex, allocation, qty = handle_one_asset(p_name, prev_allocation, asset, qty)
new_target_pos.add_asset(asset, qty)
if ex.qty != 0:
executions.append(ex)
allocations.append(allocation)
executions.append(ex)
return Executions(p_name, executions), Portfolio(p_name, allocations), new_target_pos
return executions, Portfolio(p_name, allocations), new_target_pos
if __name__ == '__main__':
asset1 = Asset(1, 'a')
asset2 = Asset(2, 'b')
asset3 = Asset(3, 'b')
target_pos = TargetPositions([asset1, asset2, asset3], [200, 300, 100])
target_pos = Positions([asset1, asset2, asset3], [200, 300, 100])
allc1 = Allocation(1, 0, 100, 0)
allc2 = Allocation(2, 0, 400, 100)
......@@ -219,8 +217,3 @@ if __name__ == '__main__':
portfolio = Portfolio('test1', [allc1, allc2])
executions, portfolio, target_pos = pass_through(target_pos, portfolio)
# -*- coding: utf-8 -*-
"""
Created on 2018-2-8
@author: cheng.li
"""
import unittest
from alphamind.model.linearmodel import ConstLinearModel
class TestModelBase(unittest.TestCase):
def test_simple_model_features(self):
model = ConstLinearModel(features=['c', 'b', 'a'])
self.assertListEqual(['a', 'b', 'c'], model.features)
\ No newline at end of file
......@@ -27,6 +27,7 @@ from alphamind.tests.analysis.test_riskanalysis import TestRiskAnalysis
from alphamind.tests.analysis.test_perfanalysis import TestPerformanceAnalysis
from alphamind.tests.analysis.test_factoranalysis import TestFactorAnalysis
from alphamind.tests.analysis.test_quantilieanalysis import TestQuantileAnalysis
from alphamind.tests.model.test_modelbase import TestModelBase
from alphamind.tests.model.test_linearmodel import TestLinearModel
from alphamind.tests.model.test_treemodel import TestTreeModel
from alphamind.tests.model.test_loader import TestLoader
......@@ -54,6 +55,7 @@ if __name__ == '__main__':
TestPerformanceAnalysis,
TestFactorAnalysis,
TestQuantileAnalysis,
TestModelBase,
TestLinearModel,
TestTreeModel,
TestLoader,
......
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