I need to parse a price series in a pandas dataframe for occurrences of two consecutive lower lows which creates a price level we call NLBL. I'm able to do this with a simple conditional (see below) but instead of the TRUE values I need the value of the third previous candle high. PLUS I need to copy that very same level forward four more times.
This is some example data:
Date Time Open High Low Close
datetime
2019-01-22 11:00:00 2019-01-22 11:00:00 2643.99 2647.47 2634.73 2634.73
2019-01-22 12:00:00 2019-01-22 12:00:00 2634.79 2638.55 2632.69 2635.94
2019-01-22 13:00:00 2019-01-22 13:00:00 2635.95 2636.35 2623.30 2631.93
2019-01-22 14:00:00 2019-01-22 14:00:00 2631.92 2632.29 2618.33 2622.66
2019-01-22 15:00:00 2019-01-22 15:00:00 2622.71 2632.90 2617.27 2625.49
2019-01-22 16:00:00 2019-01-22 16:00:00 2625.58 2633.81 2625.58 2633.81
2019-01-23 09:00:00 2019-01-23 09:00:00 2643.48 2652.44 2643.48 2650.97
2019-01-23 10:00:00 2019-01-23 10:00:00 2651.00 2653.19 2632.85 2634.47
2019-01-23 11:00:00 2019-01-23 11:00:00 2634.47 2638.55 2617.36 2617.46
2019-01-23 12:00:00 2019-01-23 12:00:00 2617.47 2627.43 2612.86 2627.31
2019-01-23 13:00:00 2019-01-23 13:00:00 2627.31 2631.70 2621.62 2629.92
2019-01-23 14:00:00 2019-01-23 14:00:00 2629.93 2635.26 2625.34 2629.21
2019-01-23 15:00:00 2019-01-23 15:00:00 2629.25 2639.22 2628.71 2636.61
2019-01-23 16:00:00 2019-01-23 16:00:00 2636.71 2639.54 2636.71 2638.60
2019-01-24 09:00:00 2019-01-24 09:00:00 2638.84 2641.03 2631.06 2636.14
2019-01-24 10:00:00 2019-01-24 10:00:00 2636.18 2647.20 2633.12 2640.49
2019-01-24 11:00:00 2019-01-24 11:00:00 2640.31 2645.37 2633.60 2644.08
2019-01-24 12:00:00 2019-01-24 12:00:00 2644.14 2644.42 2632.79 2634.31
2019-01-24 13:00:00 2019-01-24 13:00:00 2634.34 2635.16 2627.01 2633.62
2019-01-24 14:00:00 2019-01-24 14:00:00 2633.64 2638.47 2630.96 2637.04
2019-01-24 15:00:00 2019-01-24 15:00:00 2637.03 2643.21 2636.46 2642.66
2019-01-24 16:00:00 2019-01-24 16:00:00 2642.63 2643.10 2641.97 2641.99
2019-01-25 09:00:00 2019-01-25 09:00:00 2657.44 2663.57 2657.33 2661.64
2019-01-25 10:00:00 2019-01-25 10:00:00 2661.60 2671.61 2661.60 2669.49
2019-01-25 11:00:00 2019-01-25 11:00:00 2669.47 2670.50 2664.18 2669.13
2019-01-25 12:00:00 2019-01-25 12:00:00 2669.12 2672.38 2661.39 2664.88
2019-01-25 13:00:00 2019-01-25 13:00:00 2664.88 2668.49 2663.76 2667.93
2019-01-25 14:00:00 2019-01-25 14:00:00 2667.95 2669.12 2661.14 2665.27
2019-01-25 15:00:00 2019-01-25 15:00:00 2665.27 2666.52 2658.75 2663.06
2019-01-25 16:00:00 2019-01-25 16:00:00 2662.98 2664.74 2661.64 2664.14
This is how far I've come thus far:
min_data['NLBL'] = (min_data['Low'] < min_data['Low'].shift(1)) & (min_data['Low'].shift(1) < min_data['Low'].shift(2))
min_data['NLBL'] = min_data['NLBL'].shift(periods=1) # shifting downward as the trigger is valid after the close
print("\nResult:\n %s" % min_data.tail(30))
Result:
Date Time Open High Low Close \
datetime
2019-01-22 11:00:00 2019-01-22 11:00:00 2643.99 2647.47 2634.73 2634.73
2019-01-22 12:00:00 2019-01-22 12:00:00 2634.79 2638.55 2632.69 2635.94
2019-01-22 13:00:00 2019-01-22 13:00:00 2635.95 2636.35 2623.30 2631.93
2019-01-22 14:00:00 2019-01-22 14:00:00 2631.92 2632.29 2618.33 2622.66
2019-01-22 15:00:00 2019-01-22 15:00:00 2622.71 2632.90 2617.27 2625.49
2019-01-22 16:00:00 2019-01-22 16:00:00 2625.58 2633.81 2625.58 2633.81
2019-01-23 09:00:00 2019-01-23 09:00:00 2643.48 2652.44 2643.48 2650.97
2019-01-23 10:00:00 2019-01-23 10:00:00 2651.00 2653.19 2632.85 2634.47
2019-01-23 11:00:00 2019-01-23 11:00:00 2634.47 2638.55 2617.36 2617.46
2019-01-23 12:00:00 2019-01-23 12:00:00 2617.47 2627.43 2612.86 2627.31
2019-01-23 13:00:00 2019-01-23 13:00:00 2627.31 2631.70 2621.62 2629.92
2019-01-23 14:00:00 2019-01-23 14:00:00 2629.93 2635.26 2625.34 2629.21
2019-01-23 15:00:00 2019-01-23 15:00:00 2629.25 2639.22 2628.71 2636.61
2019-01-23 16:00:00 2019-01-23 16:00:00 2636.71 2639.54 2636.71 2638.60
2019-01-24 09:00:00 2019-01-24 09:00:00 2638.84 2641.03 2631.06 2636.14
2019-01-24 10:00:00 2019-01-24 10:00:00 2636.18 2647.20 2633.12 2640.49
2019-01-24 11:00:00 2019-01-24 11:00:00 2640.31 2645.37 2633.60 2644.08
2019-01-24 12:00:00 2019-01-24 12:00:00 2644.14 2644.42 2632.79 2634.31
2019-01-24 13:00:00 2019-01-24 13:00:00 2634.34 2635.16 2627.01 2633.62
2019-01-24 14:00:00 2019-01-24 14:00:00 2633.64 2638.47 2630.96 2637.04
2019-01-24 15:00:00 2019-01-24 15:00:00 2637.03 2643.21 2636.46 2642.66
2019-01-24 16:00:00 2019-01-24 16:00:00 2642.63 2643.10 2641.97 2641.99
2019-01-25 09:00:00 2019-01-25 09:00:00 2657.44 2663.57 2657.33 2661.64
2019-01-25 10:00:00 2019-01-25 10:00:00 2661.60 2671.61 2661.60 2669.49
2019-01-25 11:00:00 2019-01-25 11:00:00 2669.47 2670.50 2664.18 2669.13
2019-01-25 12:00:00 2019-01-25 12:00:00 2669.12 2672.38 2661.39 2664.88
2019-01-25 13:00:00 2019-01-25 13:00:00 2664.88 2668.49 2663.76 2667.93
2019-01-25 14:00:00 2019-01-25 14:00:00 2667.95 2669.12 2661.14 2665.27
2019-01-25 15:00:00 2019-01-25 15:00:00 2665.27 2666.52 2658.75 2663.06
2019-01-25 16:00:00 2019-01-25 16:00:00 2662.98 2664.74 2661.64 2664.14
NLBL
datetime
2019-01-22 11:00:00 True
2019-01-22 12:00:00 True
2019-01-22 13:00:00 True
2019-01-22 14:00:00 True
2019-01-22 15:00:00 True
2019-01-22 16:00:00 True
2019-01-23 09:00:00 False
2019-01-23 10:00:00 False
2019-01-23 11:00:00 False
2019-01-23 12:00:00 True
2019-01-23 13:00:00 True
2019-01-23 14:00:00 False
2019-01-23 15:00:00 False
2019-01-23 16:00:00 False
2019-01-24 09:00:00 False
2019-01-24 10:00:00 False
2019-01-24 11:00:00 False
2019-01-24 12:00:00 False
2019-01-24 13:00:00 False
2019-01-24 14:00:00 True
2019-01-24 15:00:00 False
2019-01-24 16:00:00 False
2019-01-25 09:00:00 False
2019-01-25 10:00:00 False
2019-01-25 11:00:00 False
2019-01-25 12:00:00 False
2019-01-25 13:00:00 False
2019-01-25 14:00:00 False
2019-01-25 15:00:00 False
2019-01-25 16:00:00 True
So here is where I am stuck. What I need to do from here are two things:
Replace each
Trueinmin_value['NLBL']withHight.Shift(3)- basically the highest low in the series. Also set each False to 0.Copy every
min_value['NLBL']row that is not populated with 0 forward four more times but only until it finds the next 0.
I assume a lambda expression would be appropriate but doing all this in the context of pandas has me stumped. Any ideas/insights how this can be done without resorting to a slow/ugly/annoying if loop?
This is just one example of several similar patterns I will have to implement. So solving this is a big issue for me and any help would be greatly appreciated.
Thanks in advance!
UPDATE: Someone asked for the correct output of the NLBL column:
NLBL
datetime
2019-01-22 14:00:00 2647.47
2019-01-22 15:00:00 2638.55
2019-01-22 16:00:00 2636.35
2019-01-23 09:00:00 0
2019-01-23 10:00:00 0
2019-01-23 11:00:00 0
2019-01-23 12:00:00 2652.44
2019-01-23 13:00:00 2653.19
2019-01-23 14:00:00 2653.19
2019-01-23 15:00:00 2653.19
2019-01-23 16:00:00 2653.19
2019-01-24 09:00:00 2653.19
2019-01-24 10:00:00 0
2019-01-24 11:00:00 0
2019-01-24 12:00:00 0
2019-01-24 13:00:00 0
2019-01-24 14:00:00 2645.37
2019-01-24 15:00:00 2645.37
2019-01-24 16:00:00 2645.37
2019-01-25 09:00:00 2645.37
2019-01-25 10:00:00 2645.37
2019-01-25 11:00:00 0
2019-01-25 12:00:00 0
2019-01-25 13:00:00 0
2019-01-25 14:00:00 0
2019-01-25 15:00:00 0
2019-01-25 16:00:00 2668.49
If it gets to a row with a TRUE value in the 'NLBL' column it'll count three rows backward, grab the 'High' value and replace TRUE with that one. It then copies that same 'High' value to the following four rows.
However if it finds a new TRUE it will stop copying forward and use the new High value.
Hope this makes sense.