Ich habe einen OHLC-Preisdatensatz, den ich von CSV in einen Pandas-Datenrahmen analysiert und auf 15-Minuten-Balken neu abgetastet habe:
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 500047 entries, 1998-05-04 04:45:00 to 2012-08-07 00:15:00
Freq: 15T
Data columns:
Close 363152 non-null values
High 363152 non-null values
Low 363152 non-null values
Open 363152 non-null values
dtypes: float64(4)
Ich möchte verschiedene berechnete Spalten hinzufügen, beginnend mit einfachen Spalten wie dem Periodenbereich (HL) und dann Booleschen Werten, um das Auftreten von Preismustern anzuzeigen, die ich definieren werde - z. B. ein Hammerkerzenmuster, für das eine Beispieldefinition gilt:
def closed_in_top_half_of_range(h,l,c):
return c > l + (h-l)/2
def lower_wick(o,l,c):
return min(o,c)-l
def real_body(o,c):
return abs(c-o)
def lower_wick_at_least_twice_real_body(o,l,c):
return lower_wick(o,l,c) >= 2 * real_body(o,c)
def is_hammer(row):
return lower_wick_at_least_twice_real_body(row["Open"],row["Low"],row["Close"]) \
and closed_in_top_half_of_range(row["High"],row["Low"],row["Close"])
Grundproblem: Wie ordne ich die Funktion der Spalte zu, insbesondere dort, wo ich auf mehr als eine andere Spalte oder die gesamte Zeile oder was auch immer verweisen möchte?
Dieser Beitrag befasst sich mit dem Hinzufügen von zwei berechneten Spalten aus einer einzelnen Quellenspalte, was nahe ist, aber nicht ganz.
Und etwas weiter fortgeschritten: Wie kann ich bei Preismustern, die mit Bezug auf mehr als einen einzelnen Balken (T) ermittelt werden, innerhalb der Funktionsdefinition auf verschiedene Zeilen (z. B. T-1, T-2 usw.) verweisen?
map(f, col1, col2)
viel schneller alsdf.apply(..., axis=1)
. Die Karte benötigt 0,35 Sekunden, während für einen Datenrahmen mit 1 Million Zeilen 26 Sekunden benötigt werden. Irgendeine Idee warum? (Python 2.7 und Pandas 0.18.1)df = df.copy()
oben beschrieben kopieren ... dies kann jedoch besser als neue Frage beantwortet werden.Für den zweiten Teil Ihrer Frage können Sie beispielsweise auch Folgendes verwenden
shift
:df['t-1'] = df['t'].shift(1)
t-1
würde dann die Werte von t eine Zeile oben enthalten.http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.shift.html
quelle
Die ersten vier Funktionen, die Sie auflisten, funktionieren auch mit Vektoren, mit der Ausnahme, dass lower_wick angepasst werden muss. Etwas wie das,
def lower_wick_vec(o, l, c): min_oc = numpy.where(o > c, c, o) return min_oc - l
wobei o, l und c Vektoren sind. Sie können dies stattdessen auf diese Weise tun, indem Sie nur den df als Eingabe verwenden und die Verwendung von numpy vermeiden, obwohl dies viel langsamer sein wird:
def lower_wick_df(df): min_oc = df[['Open', 'Close']].min(axis=1) return min_oc - l
Die anderen drei arbeiten mit Spalten oder Vektoren so wie sie sind. Dann können Sie mit beenden
def is_hammer(df): lw = lower_wick_at_least_twice_real_body(df["Open"], df["Low"], df["Close"]) cl = closed_in_top_half_of_range(df["High"], df["Low"], df["Close"]) return cl & lw
Bit - Operatoren können Satz Logik auf boolean Vektoren durchführen,
&
fürand
,|
füror
usw. genug ist , vollständig die Beispielrechnungen vektorisieren Sie gab und sollte relativ schnell sein. Sie könnten wahrscheinlich noch schneller werden, indem Sie vorübergehend mit den den Daten zugrunde liegenden Numpy-Arrays arbeiten, während Sie diese Berechnungen durchführen.Für den zweiten Teil würde ich empfehlen, eine Spalte einzuführen, die das Muster für jede Zeile angibt, und eine Familie von Funktionen zu schreiben, die sich mit jedem Muster befassen. Gruppieren Sie dann nach dem Muster und wenden Sie die entsprechende Funktion auf jede Gruppe an.
quelle