Commit 570322c4 authored by Dr.李's avatar Dr.李

added execution pipeline

parent cae62afe
...@@ -21,7 +21,7 @@ class ExecutionPipeline(object): ...@@ -21,7 +21,7 @@ class ExecutionPipeline(object):
turn_over, planed_pos = 0., target_pos turn_over, planed_pos = 0., target_pos
for executor in self.executors: for executor in self.executors:
turn_over, planed_pos = executor.execute(target_pos) turn_over, planed_pos = executor.execute(planed_pos)
executed_pos = planed_pos executed_pos = planed_pos
......
...@@ -8,6 +8,7 @@ Created on 2017-9-22 ...@@ -8,6 +8,7 @@ Created on 2017-9-22
from typing import Tuple from typing import Tuple
import pandas as pd import pandas as pd
from PyFin.Math.Accumulators import MovingStandardDeviation from PyFin.Math.Accumulators import MovingStandardDeviation
from PyFin.Math.Accumulators import MovingAverage
from alphamind.execution.baseexecutor import ExecutorBase from alphamind.execution.baseexecutor import ExecutorBase
...@@ -16,6 +17,7 @@ class TargetVolExecutor(ExecutorBase): ...@@ -16,6 +17,7 @@ class TargetVolExecutor(ExecutorBase):
def __init__(self, window=30, target_vol=0.01): def __init__(self, window=30, target_vol=0.01):
super().__init__() super().__init__()
self.m_vol = MovingStandardDeviation(window=window, dependency='return') self.m_vol = MovingStandardDeviation(window=window, dependency='return')
self.m_leverage = MovingAverage(window=window, dependency='leverage')
self.target_vol = target_vol self.target_vol = target_vol
self.multiplier = 1. self.multiplier = 1.
...@@ -28,11 +30,16 @@ class TargetVolExecutor(ExecutorBase): ...@@ -28,11 +30,16 @@ class TargetVolExecutor(ExecutorBase):
return turn_over, target_pos return turn_over, target_pos
else: else:
c_vol = self.m_vol.result() c_vol = self.m_vol.result()
self.multiplier = c_vol / self.target_vol c_leverage = self.m_leverage.result()
self.multiplier = self.target_vol / c_vol * c_leverage
candidate_pos = target_pos.copy() candidate_pos = target_pos.copy()
candidate_pos['weight'] = candidate_pos.weight.values / self.multiplier candidate_pos['weight'] = candidate_pos.weight.values * self.multiplier
turn_over = self.calc_turn_over(candidate_pos, self.current_pos) turn_over = self.calc_turn_over(candidate_pos, self.current_pos)
return turn_over, candidate_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): def update(self, data_dict: dict):
self.m_vol.push(data_dict) self.m_vol.push(data_dict)
# -*- 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)
...@@ -25,13 +25,13 @@ class TestTargetVolExecutor(unittest.TestCase): ...@@ -25,13 +25,13 @@ class TestTargetVolExecutor(unittest.TestCase):
return_2 = np.random.randn(2000, n) * 0.2 return_2 = np.random.randn(2000, n) * 0.2
return_total = np.concatenate((return_1, return_2)) return_total = np.concatenate((return_1, return_2))
weigths = np.ones(n) / n weights = np.ones(n) / n
codes = np.array(list(range(n))) codes = np.array(list(range(n)))
ret_deq = deque(maxlen=window) ret_deq = deque(maxlen=window)
for i, row in enumerate(return_total): for i, row in enumerate(return_total):
pos = pd.DataFrame({'code': codes, 'weight': weigths}) pos = pd.DataFrame({'code': codes, 'weight': weights})
turn_over, executed_pos = executor.execute(pos) turn_over, executed_pos = executor.execute(pos)
if i >= window: if i >= window:
...@@ -41,7 +41,7 @@ class TestTargetVolExecutor(unittest.TestCase): ...@@ -41,7 +41,7 @@ class TestTargetVolExecutor(unittest.TestCase):
executed_pos.equals(pos) executed_pos.equals(pos)
executor.set_current(executed_pos) executor.set_current(executed_pos)
daily_return = row @ weigths daily_return = row @ weights
data_dict = {'return': daily_return} data_dict = {'return': daily_return}
executor.update(data_dict=data_dict) executor.update(data_dict=data_dict)
ret_deq.append(daily_return) ret_deq.append(daily_return)
......
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