Ausgabe
Ich habe einen Datenrahmen wie folgt:
close
formated
2017-01-03 09:30:00 29.9713
2017-01-03 09:31:00 29.0622
2017-01-03 09:32:00 29.0750
2017-01-03 09:33:00 29.0276
2017-01-03 09:34:00 29.0375
... ...
2022-08-19 09:30:00 173.5500
2022-08-19 09:31:00 173.4494
2022-08-19 09:32:00 173.3400
2022-08-19 09:33:00 173.3900
2022-08-19 09:34:00 173.2600
Der df enthält einen Preiswert für jede Minute des Tages von 9:30 bis 16:00 Uhr. Ich suche den maximal möglichen Gewinn für jede Minute des Tages.
Ich mache derzeit so etwas:
df['Profit'] = (df.groupby(pd.Grouper(freq='D'))['close'].transform('max') - df['close']).div(df['close'])
Dies gibt mir den Prozentsatz des Gewinns für jede Zeile zum höchsten Wert des Tages.
Allerdings ist dieser Ansatz fehlerhaft, da er die Gewinnprozente auch aus Zeitstempeln errechnet, nachdem der Tageshöchstwert bereits erreicht wurde.
Aber ich möchte nicht den Maximalwert für den ganzen Tag, sondern den Maximalwert pro Tag mit nur den Zeitstempeln, die nach der Zeile im Datenrahmen kommen, den wir gerade betrachten.
Der Gewinn ist definiert als die Differenz zwischen dem Wert in dieser Minute und dem Maximalwert aller folgenden Minuten desselben Tages.
Gewünschte Ausgabe:
close Profit abs. Profit perc.
formated
2017-01-03 09:30:00 29.9713 0.0 0.0
2017-01-03 09:31:00 29.0622 0.0128 0.0004404
2017-01-03 09:32:00 29.0750 0.0 0.0
2017-01-03 09:33:00 29.0276 0.0099 0.0003410
2017-01-03 09:34:00 29.0375 0.0 0.0
... ... ... ...
Bitte keine Lösungen, die den Datenrahmen in einer for-Schleife durchlaufen, da dies extrem langsam ist.
Lösung
Sie können die cummax
Funktion von Pandas verwenden, um das kumulierte Maximum über jeden Tag zu berechnen. Sie müssen es jedoch umgekehrt anwenden.
wenn wir das stündlich machen, zur Erklärung:
>>> example_df
date price
2020-01-01 00:00 1
2020-01-01 01:00 2
2020-01-01 03:00 1
2020-01-01 04:00 7
2020-01-01 05:00 5
2020-01-01 06:00 2
2020-01-01 07:00 4
>>> example_df.reverse_cummax()
date price reverse_cummax
2020-01-01 00:00 1 7
2020-01-01 01:00 2 7
2020-01-01 03:00 1 7
2020-01-01 04:00 7 7
2020-01-01 05:00 5 5
2020-01-01 06:00 2 4
2020-01-01 07:00 4 4
so würde die Ausgabe einer reverse_cummax-Funktion aussehen.
Wir können nicht direkt cummax
von Pandas verwenden, und es gibt keine einfache Möglichkeit, dies umzukehren, außer den gesamten Datenrahmen umzukehren. Wir müssen eine Unterfunktion erstellen, die die Werte der Spalten in den “gruppiert nach”-Datenrahmen, an denen wir interessiert sind, direkt umkehrt, und sie dann wieder umkehren, wenn wir fertig sind:
def reverse_cummax(df_day):
return df_day.loc[::-1, "close"].cummax()[::-1]
# This function produces a MultiLevelIndex, but we want our initial index
# back, so we need to drop a level
df["reverse_cummax"] = df.groupby(pd.Grouper(freq='D')).apply(reverse_cummax).droplevel(0)
dann können Sie Ihren Gewinn erzielen, indem Sie jeden Wert von dem täglichen Höchstwert abziehen, der kommen wird ( reverse_cummax
)
df["profit abs"] = df["reverse_cummax"] - df["close"]
df["profit percentage"] = df["profit abs"]/df["close"]
Bearbeitet , um die verbesserte Lösung hinzuzufügen, wie von dermen vorgeschlagen
Beantwortet von – Florent Monin
Antwort geprüft von – Senaida (FixError Volunteer)