Vectorize maximum drawdown stop loss logic

Viewed 34

I have the following code that works as intended in a for loop:

import pandas as pd
import numpy as np

returns = pd.DataFrame(np.random.normal(scale=0.01,size=[1000,7]))

signal = pd.DataFrame(np.random.choice([1,np.nan],p=(0.1,0.9),size=[1000,7]))

window=20

breach = -0.03

positions = signal.copy(); positions[:] = np.nan

pf_returns = pd.Series(index=positions.index)

max_dd = pf_returns.copy()

for i in range(len(positions)):
    
    #Positions are just the number of signals divided by the total active ones
    positions.iloc[i] = signal.ffill().shift().div(signal.ffill().shift().sum(axis=1),axis=0).iloc[i]

    pf_returns.iloc[i] = (positions.iloc[i] * returns.iloc[i]).sum()

    equity_line = (pf_returns.iloc[max(i-window,0):i+1]+1).iloc[:i+1].cumprod()
    
    max_dd.iloc[i] = (equity_line/equity_line.cummax()-1).rolling(window, min_periods=1).min().iloc[-1]
    
    if max_dd.iloc[i] <= breach and i != len(positions)-1:
        
        signal.iloc[i+1] = 0

Is it somehow possible to vectorize it? I thought in computing the equity_line at once (definitely possible without all these ilocs), however it then changes the upcoming values. I also thought somehow to a loop that runs in chunks (until next max_dd is found basically) but I am not sure if there is any possibility to vectorize or make this more efficient.

My desired outcome is basically to reproduce what the loops does (in terms of positions, if you wish, and consequently pf_returns) in a more efficient way.

0 Answers
Related