2

I am trying to find cumulative sum of peak prominences in python only with left bases for a price series. In other words it is the sum of reverse of drawdowns or recovery.

First i tried with following:

from scipy.signal import find_peaks, peak_prominences
import matplotlib.pyplot as plt

x = np.linspace(0, 6 * np.pi, 1000)
x = np.sin(x) + 0.6 * np.sin(2.6 * x)

peaks, _ = find_peaks(x)
prominences = peak_prominences(x, peaks)[0]
prominences

contour_heights = x[peaks] - prominences
plt.plot(x)
plt.plot(peaks, x[peaks], "x")
plt.vlines(x=peaks, ymin=contour_heights, ymax=x[peaks])
plt.show()

The result and the plot was a good starting point. But some issues are the following:

  • peaks are being compared to left and right lowest values. I need the comparison with only with left low value.
  • peaks should only be compared with previous trough/ low value not the lowest value in the trough
  • if peaks are compared to the previous trough / lowest value in the trough then intermediate prominence should be ignored.

what i got from the code as a starting point

my required result

once things are visually confirmed i need to calculate the sum of all the peak prominences ( distance between peak to trough ). Please help.

prabinseth
  • 33
  • 4

1 Answers1

1

Assuming I have not misunderstood your requirements (if so please tell) this may solve your problem:

You can compute the "left prominence" by using the left_bases as returned by peak_prominences:

from scipy.signal import find_peaks, peak_prominences
import matplotlib.pyplot as plt

x = np.linspace(0, 6 * np.pi, 1000)
x = np.sin(x) + 0.6 * np.sin(2.6 * x)

peaks, _ = find_peaks(x)
_, left_bases, _ = peak_prominences(x, peaks)
left_prominences = x[peaks] - x[left_bases]

This should solve your first problem. If I understand you correctly, you want to ignore peaks after the left base of a larger peak:

keep = ~(
    (left_prominences[:-1] < left_prominences[1:]) 
    & (peaks[:-1] > left_bases[1:])
)
keep = np.concatenate((keep, [True]))  # last peak is always kept
peaks = peaks[keep]
left_prominences = left_prominences[keep]

plt.plot(x)
plt.vlines(x=peaks, ymin=x[peaks]-left_prominences, ymax=x[peaks])

resulting plot

Finally the total sum is easily computed with:

np.sum(left_prominences)  # returns 8.740800984535955

This approach should be reasonable fast.

lagru
  • 196
  • 7