class TargetVolExecutor(ExecutorBase): def __init__(self, window=30, target_vol=0.01): super().__init__() self.m_vol = MovingStandardDeviation(window, 'return') self.m_leverage = MovingAverage(window, 'leverage') self.target_vol = target_vol self.multiplier = 1. def execute(self, target_pos: pd.DataFrame) -> Tuple[float, pd.DataFrame]: if not self.m_vol.isFull(): if self.current_pos.empty: turn_over = target_pos.weight.abs().sum() else: turn_over = self.calc_turn_over(target_pos, self.current_pos) return turn_over, target_pos else: c_vol = self.m_vol.result() c_leverage = self.m_leverage.result() self.multiplier = self.target_vol / c_vol * c_leverage candidate_pos = target_pos.copy() candidate_pos[ 'weight'] = candidate_pos.weight.values * self.multiplier turn_over = self.calc_turn_over(candidate_pos, self.current_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): self.m_vol.push(data_dict)
def testShiftValueHolder(self): ma = MovingAverage(10, 'close') with self.assertRaises(ValueError): _ = Shift(ma, N=0) test = Shift(ma, N=1) test.push(dict(close=2.0)) ma.push(dict(close=2.0)) previous = ma.result() test.push(dict(close=5.0)) ma.push(dict(close=5.0)) self.assertAlmostEqual(previous, test.result()) previous = ma.result() test.push(dict(close=10.0)) self.assertAlmostEqual(previous, test.result())
def testMovingAverager(self): window = 120 total = 2500 mv = MovingAverage(window, dependency='z') runningSum = 0.0 con = [] for i in range(total): value = float(i) con.append(value) mv.push(dict(z=value)) runningSum += value if i >= window: runningSum -= con[0] con = con[1:] if i >= window - 1: expected = runningSum / window calculated = mv.result() self.assertAlmostEqual(calculated, expected, 15, "at index {0:d}\n" "Average expected: {1:f}\n" "Average calculated: {2:f}".format(i, expected, calculated))
def testMovingAverager(self): window = 120 total = 2500 mv = MovingAverage(window, dependency='z') runningSum = 0.0 con = [] for i in range(total): value = float(i) con.append(value) mv.push(dict(z=value)) runningSum += value if i >= window: runningSum -= con[0] con = con[1:] if i >= window - 1: expected = runningSum / window calculated = mv.result() self.assertAlmostEqual( calculated, expected, 15, "at index {0:d}\n" "Average expected: {1:f}\n" "Average calculated: {2:f}".format(i, expected, calculated))