Python Dataframe new column based on conditional statement
Question: I have a dataframe consisting of a few columns of custom calculations for a
trading strategy. I want to add a new column called 'Signals' to this
dataframe, consisting of 0s and 1s (long only strategy). The signals will be
generated on the following code, each item in this code is a separate column
in the dataframe:

    
    
    if:
        open_price > low_sigma.shift(1) and high_price > high_sigma.shift(1):
            signal = 1
        else:
            signal = 0
    

From my understanding, if statements are not efficient for dataframes. In
addition, I haven't been able to get this to output as desired. How do you
recommend I generate the signal and add it to the dataframe?


Answer: You could assign `df['Signals']` to the boolean condition itself, then use
`astype` to convert the booleans to 0s and 1s:

    
    
    df['Signals'] = (((df['open_price'] > df['low_sigma'].shift(1)) 
        & (df['high_price'] > df['high_sigma'].shift(1)))
        .astype('int'))
    

for example,

    
    
    import pandas as pd
    df = pd.DataFrame({
        'open_price': [1,2,3,4],
        'low_sigma': [1,3,2,4],
        'high_price': [10,20,30,40],
        'high_sigma': [10,40,20,30]})
    
    #    high_price  high_sigma  low_sigma  open_price
    # 0          10          10          1           1
    # 1          20          40          3           2
    # 2          30          20          2           3
    # 3          40          30          4           4
    
    mask = ((df['open_price'] > df['low_sigma'].shift(1)) 
            & (df['high_price'] > df['high_sigma'].shift(1)))
    # 0    False
    # 1     True
    # 2    False
    # 3     True
    # dtype: bool
    
    df['Signals'] = mask.astype('int')
    print(df)
    

yields

    
    
       high_price  high_sigma  low_sigma  open_price  Signals
    0          10          10          1           1        0
    1          20          40          3           2        1
    2          30          20          2           3        0
    3          40          30          4           4        1
    

