'Modify code to capture values greater than - instead of exact match

The following code works well for identifying whether a value is hit or missed over following rows and giving the output column showing the time the condition was met.

import datetime,numpy as np,pandas as pd;
nan = np.nan;

a = pd.DataFrame(  {'price': {datetime.time(9, 0): 1,   datetime.time(10, 0): 0,   datetime.time(11, 0): 3,   datetime.time(12, 0): 4,   datetime.time(13, 0): 7,   datetime.time(14, 0): 6,   datetime.time(15, 0): 5,   datetime.time(16, 0): 4,   datetime.time(17, 0): 0,   datetime.time(18, 0): 2,   datetime.time(19, 0): 4,   datetime.time(20, 0): 7},  'reversal': {datetime.time(9, 0): nan,   datetime.time(10, 0): nan,   datetime.time(11, 0): nan,   datetime.time(12, 0): nan,   datetime.time(13, 0): nan,
  datetime.time(14, 0): 6.0,   datetime.time(15, 0): nan,   datetime.time(16, 0): nan,   datetime.time(17, 0): nan,   datetime.time(18, 0): nan,   datetime.time(19, 0): nan,   datetime.time(20, 0): nan}});


a['target_hit_time']=a['target_miss_time']=nan;
a['target1']=a['reversal']+1;
a['target2']=a['reversal']-a['reversal'];
a.sort_index(1,inplace=True);

hits = a.ix[:,:-2].dropna();

for row,hit in hits.iterrows():

        forwardRows = [row]<a['price'].index.values

        targetHit = a.index.values[(hit['target1']==a['price'].values) & forwardRows][0];
        targetMiss = a.index.values[(hit['target2']==a['price'].values) & forwardRows][0];

        if targetHit>targetMiss:
            a.loc[row,"target_miss_time"] = targetMiss;
        else:
            a.loc[row,"target_hit_time"] = targetHit;


a

This image shows the output from the above code which can easily be reproduced by running this code:

current working code

The issue I have is that when this code is utilised on real data the price may not exactly match and/or may gap though a value. So if we look at the following image:

desired

We see that target1 criteria would be met if we were looking for a value >= 7.5 and not just looking for the value 7.5. How can I modify the code to achieve this?



Solution 1:[1]

Some ifs and thats all :D...

import datetime,numpy as np,pandas as pd;
nan = np.nan;

a = pd.DataFrame(  {'price': {datetime.time(9, 0): 1,   datetime.time(10, 0): 0,   datetime.time(11, 0): 3,   datetime.time(12, 0): 4,   datetime.time(13, 0): 7,   datetime.time(14, 0): 6,   datetime.time(15, 0): 5,   datetime.time(16, 0): 4,   datetime.time(17, 0): 2,   datetime.time(18, 0): 2,   datetime.time(19, 0): 4,   datetime.time(20, 0): 8},  'reversal': {datetime.time(9, 0): nan,   datetime.time(10, 0): nan,   datetime.time(11, 0): nan,   datetime.time(12, 0): nan,   datetime.time(13, 0): nan,
  datetime.time(14, 0): 6.0,   datetime.time(15, 0): nan,   datetime.time(16, 0): nan,   datetime.time(17, 0): nan,   datetime.time(18, 0): nan,   datetime.time(19, 0): nan,   datetime.time(20, 0): nan}});


a['target_hit_time']=a['target_miss_time']=nan;
a['target1']=a['reversal']+1;
a['target2']=a['reversal']-a['reversal'];
a.sort_index(1,inplace=True);

hits = a.ix[:,:-2].dropna();

for row,hit in hits.iterrows():

        forwardRows = a[a.index.values > row];
        targetHit = hit['target1']<=forwardRows['price'].values;
        targetMiss = hit['target2']==forwardRows['price'].values;
        targetHit = forwardRows[targetHit].head(1).index.values;
        targetMiss = forwardRows[targetMiss].head(1).index.values;

        targetHit, targetMiss = \
        targetHit[0] if targetHit else [], \
        targetMiss[0] if targetMiss else [];

        goMiss,goHit = False,False
        if targetHit and targetMiss:
            if targetHit>targetMiss: goMiss=True;
            else: goHit=True;
        elif targetHit and not targetMiss:goHit = True;
        elif not targetHit and targetMiss:goMiss = True;

        if goMiss:a.loc[row,"target_miss_time"] = targetMiss;
        elif goHit:a.loc[row,"target_hit_time"] = targetHit;



print '#'*50
print a
'''
##################################################
          price  reversal  target1  target2 target_hit_time  target_miss_time
09:00:00      1       NaN      NaN      NaN             NaN               NaN
10:00:00      0       NaN      NaN      NaN             NaN               NaN
11:00:00      3       NaN      NaN      NaN             NaN               NaN
12:00:00      4       NaN      NaN      NaN             NaN               NaN
13:00:00      7       NaN      NaN      NaN             NaN               NaN
14:00:00      6       6.0      7.0      0.0        20:00:00               NaN
15:00:00      5       NaN      NaN      NaN             NaN               NaN
16:00:00      4       NaN      NaN      NaN             NaN               NaN
17:00:00      2       NaN      NaN      NaN             NaN               NaN
18:00:00      2       NaN      NaN      NaN             NaN               NaN
19:00:00      4       NaN      NaN      NaN             NaN               NaN
20:00:00      8       NaN      NaN      NaN             NaN               NaN
'''

Solution 2:[2]

Without modifying your code heavily, this is what I came up with:

import numpy as np

for row,hit in hits.iterrows():
        print ("row", row)
        print ("hit",hit)

        forwardRows = a[a.index.values > row]

        targetHit = forwardRows[(hit['target1'] <= forwardRows['price'].values)].head(1).index.values

        targetMiss = forwardRows[(hit['target2'] >= forwardRows['price'].values)].head(1).index.values

        if targetHit>targetMiss:
            a.loc[row,"target_miss_time"] = targetMiss
        else:
            a.loc[row,"target_hit_time"] = targetHit

    price   reversal    target1 target2 target_hit_time target_miss_time
09:00:00    1   NaN NaN NaN NaN NaN
10:00:00    0   NaN NaN NaN NaN NaN
11:00:00    3   NaN NaN NaN NaN NaN
12:00:00    4   NaN NaN NaN NaN NaN
13:00:00    7   NaN NaN NaN NaN NaN
14:00:00    6   6.5 7.5 0.0 [20:00:00]  NaN
15:00:00    5   NaN NaN NaN NaN NaN
16:00:00    4   NaN NaN NaN NaN NaN
17:00:00    2   NaN NaN NaN NaN NaN
18:00:00    2   NaN NaN NaN NaN NaN
19:00:00    4   NaN NaN NaN NaN NaN
20:00:00    8   NaN NaN NaN NaN NaN

This is still to be improved since targetHit, targetMiss return an array and you need to check if there are any elements in array and if there are elements in both arrays - you need to compare first alements. Right now it only works if one array is empty.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2