@ChrisLi: Dann bring deine Daten bzw. Dataframe in Ordnung.
Irgendo wird der ja erstellt. Ich hoffe aus einem Haufen Daten. Und Pandas erkennt eigentlich sehr gut den Typen der Felder. Wenn der nicht stimmt ist das ein Zeichen dafür, dass etwas mit den Daten nicht stimmt (mindestens ein Feld enthält nicht, was man denkt) oder der Datsframe wurde falsch erstellt.
Jetzt landen wir wieder bei dem Pandas Tutorial und der Frage, wie du den DF erstellst.
iterrows über mehrere dataframes per loop
Ich verbinde mit via der MT5-Api mit einem Broker, dann:
dann:
Auch wenn ich :
bleibt es beim 'str' object..
Tutorials ja, ich bin dran.
Code: Alles auswählen
rates_H1 = mt5.copy_rates_range("USTEC", mt5.TIMEFRAME_H1, utc_from, utc_to)
Code: Alles auswählen
df_H1 = pd.DataFrame(rates_H1)
Code: Alles auswählen
df_H1['time']=pd.to_datetime(df_H1['time'], unit='s')
Tutorials ja, ich bin dran.
-
- User
- Beiträge: 510
- Registriert: Mittwoch 13. November 2019, 08:38
Wenn du diese Fehlermeldung bei dem Code bekommst, dann sind df_M5, df_M30, df_H1 keine DataFrames.
Hier sieht man auch, wie ich halt gruselig mit iterrows() leere DFs befülle; jedenfalls liefert mir das die Daten, die ich sehen will.
Code: Alles auswählen
# logging into broker with credentials..
...
..
if authorized:
account_info_dict = mt5.account_info()._asdict()
for prop in account_info_dict:
print(" {}={}".format(prop, account_info_dict[prop]))
else:
print("failed to connect at account #{}, error code: {}".format(account, mt5.last_error()))
# set time zone to UTC
timezone = pytz.timezone("Etc/UTC")
# select symbol
selected=mt5.symbol_select("EURUSD",True)
if not selected:
print("failed to select symbol")
mt5.shutdown()
quit()
# create 'datetime' object in UTC time zone to avoid the implementation of a local time zone offset
utc_from = datetime(2023, 1, 1, tzinfo=timezone)
utc_to = datetime(2023, 10, 3, tzinfo=timezone)
# get the bar data
rates_H1 = mt5.copy_rates_range("EURUSD", mt5.TIMEFRAME_H1, utc_from, utc_to)
# shut down connection to the MetaTrader 5 terminal
mt5.shutdown()
# put received rates into dataframe
df_H1 = pd.DataFrame(rates_H1)
# convert time in seconds into the datetime format
df_H1['time']=pd.to_datetime(df_H1['time'], unit='s')
# create new dataframes for filtered data
df_stats_H1_08 = pd.DataFrame(columns=('time', 'high08', 'low08'))
df_stats_H1_812 = pd.DataFrame(columns=('time', 'high812', 'low812'))
#
filter08 = df_H1.time.dt.hour.between(0, 8, 'both')
filter812 = df_H1.time.dt.hour.between(8, 12, 'both')
filter0 = df_H1.time.dt.hour == 0
df_H1_filtered = df_H1[["time", "high", "low", ]]
high08 = 0
low08 = 1000
for pos, d in df_H1_filtered.iterrows():
if (d.time.hour >= 0) & (d.time.hour <= 8):
if (d.high > high08):
high08 = d.high
if (d.low < low08):
low08 = d.low
if (d.time.hour == 8):
df_stats_H1_08.loc[pos] = [d.time, high08, low08]
high08 = 0
low08 = 1000
high812 = 0
low812 = 1000
for pos, d in df_H1_filtered.iterrows():
if (d.time.hour >= 8) & (d.time.hour <= 12):
if (d.high > high812):
high812 = d.high
if (d.low < low812):
low812 = d.low
if (d.time.hour == 20):
df_stats_H1_812.loc[pos] = [d.time, high812, low812]
high812 = 0
low812 = 1000
# resetting index that merging dfs work
df_stats_H1_08.reset_index(inplace=True)
df_stats_H1_812.reset_index(inplace=True)
print("df_stats_H1_08: \n", df_stats_H1_08)
print("df_stats_H1_812: \n", df_stats_H1_812)
# adding cols to df
df_stats_H1_08['high812'] = df_stats_H1_812['high812']
df_stats_H1_08['low812'] = df_stats_H1_812['low812']
df_stats_H1_08['high2high'] = df_stats_H1_08['high812'] - df_stats_H1_08['high08']
df_stats_H1_08['low2low'] = df_stats_H1_08['low812'] - df_stats_H1_08['low08']
print(df_H1.dtypes)
for df in df_H1:
print(df)
condition = (df.time.dt.hour >= 0) & (df.time.dt.hour <= 8)
df["h2l"] = df[condition].high - df[condition].low
print("df: \n", df)
Code: Alles auswählen
Columns: [index, time, high812, low812]
Index: []
time datetime64[ns]
open float64
high float64
low float64
close float64
tick_volume uint64
spread int32
real_volume uint64
dtype: object
- __blackjack__
- User
- Beiträge: 13931
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Keine Ahnung was Du genau mit dem letzten Satz sagen willst, aber `df` in der letzten Schleife ist natürlich *kein* DataFrame, denn wenn man *über* einen DataFrame iteriert bekommt man als einzelne Elemente keine DataFrames. Was sollten die denn auch enthalten beziehungsweise wie sollten die aussehen?
Wie schon gesagt, man befüllt keine leeren DataFrame-Objekte Datensatz für Datensatz. Das ist falsch. Nicht nur ein bisschen unschön sondern falsch. Und ja, das funktioniert. Ich kann auch meinen Nachbarn erschiessen wenn der Fernseher zu laut ist. Das funktioniert. Ist aber mindestens genau so falsch.
Wenn `authorized` nicht zutrifft macht der Code einfach weiter als wäre nix. Ich bin mir ziemlich sicher das wird nicht funktionieren.
`quit()` gibt es eigentlich gar nicht. Die Funktion ist für den interaktiven Interpreter gedacht und hat in Programmen nix zu suchen. Falls jetzt der nächste Impuls `sys.exit()` sein sollte: Das ist dazu da um mindestens potentiell einen anderen Rückgabecode als 0 an den aufrufenden Prozess zu übermitteln. Könnte man hier vielleicht sogar sinnvoll machen.
Den `mt5.shutdown()`-Aufruf sollte man mit einem ``try``/``finally`` sicherstellen.
Insgesamt sieht das nach zu viel Code am Stück aus. Und das steht auch alles auf Modulebene. Das sollte man sinnvoll auf Funktionen aufteilen, auch um einzelne Teile leichter testen zu können. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Wie schon gesagt, man befüllt keine leeren DataFrame-Objekte Datensatz für Datensatz. Das ist falsch. Nicht nur ein bisschen unschön sondern falsch. Und ja, das funktioniert. Ich kann auch meinen Nachbarn erschiessen wenn der Fernseher zu laut ist. Das funktioniert. Ist aber mindestens genau so falsch.
Wenn `authorized` nicht zutrifft macht der Code einfach weiter als wäre nix. Ich bin mir ziemlich sicher das wird nicht funktionieren.
`quit()` gibt es eigentlich gar nicht. Die Funktion ist für den interaktiven Interpreter gedacht und hat in Programmen nix zu suchen. Falls jetzt der nächste Impuls `sys.exit()` sein sollte: Das ist dazu da um mindestens potentiell einen anderen Rückgabecode als 0 an den aufrufenden Prozess zu übermitteln. Könnte man hier vielleicht sogar sinnvoll machen.
Den `mt5.shutdown()`-Aufruf sollte man mit einem ``try``/``finally`` sicherstellen.
Insgesamt sieht das nach zu viel Code am Stück aus. Und das steht auch alles auf Modulebene. Das sollte man sinnvoll auf Funktionen aufteilen, auch um einzelne Teile leichter testen zu können. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
— Scott Bellware
Jetzt hast Du ja immer noch for-Schleifen obwohl Du ja schon die passenden Filter definiert hast. Warum?
Was soll auch diese komische if-Bedingungen, mit denen Du low und high auf 0 bis 1000 einschränkst? Ist das wirklich die beabsichtigte Wirkung?
Hast Du wirklich exakt gleich viele Elemente von 0 bis 8 Uhr wie von 8 bis 12 Uhr? Weil sonst funktioniert ja die Differenzbildung nicht. Und was soll das überhaupt bedeuten, einen Wert von irgendwann zwischen 0 und 8 von einem beliebigen zwischen 8 und 12 abzuziehen?
Von Deinem Code bleibt also nicht mehr viel übrig, weil man mit Pandas solche Operationen sehr kompakt schreiben kann:
Was soll auch diese komische if-Bedingungen, mit denen Du low und high auf 0 bis 1000 einschränkst? Ist das wirklich die beabsichtigte Wirkung?
Hast Du wirklich exakt gleich viele Elemente von 0 bis 8 Uhr wie von 8 bis 12 Uhr? Weil sonst funktioniert ja die Differenzbildung nicht. Und was soll das überhaupt bedeuten, einen Wert von irgendwann zwischen 0 und 8 von einem beliebigen zwischen 8 und 12 abzuziehen?
Von Deinem Code bleibt also nicht mehr viel übrig, weil man mit Pandas solche Operationen sehr kompakt schreiben kann:
Code: Alles auswählen
def read_data():
try:
selected=mt5.symbol_select("EURUSD",True)
if not selected:
raise RuntimeError("failed to select symbol")
timezone = pytz.timezone("Etc/UTC")
utc_from = datetime(2023, 1, 1, tzinfo=timezone)
utc_to = datetime(2023, 10, 3, tzinfo=timezone)
rates_H1 = mt5.copy_rates_range("EURUSD", mt5.TIMEFRAME_H1, utc_from, utc_to)
finally:
mt5.shutdown()
return rates_H1
def main():
...
df_H1 = pd.DataFrame(read_data())
df_H1['time']=pd.to_datetime(df_H1['time'], unit='s')
df_H1['low'] = df_H1['low'].clip_upper(1000)
df_H1['high'] = df_H1['high'].clip_lower(0)
filter08 = df_H1.time.dt.hour.between(0, 8, 'both')
filter812 = df_H1.time.dt.hour.between(8, 12, 'both')
df_stats_H1_08 = df_H1[filter08]
df_stats_H1_812 = df_H1[filter812]
df_stats_H1_08.reset_index(inplace=True)
df_stats_H1_812.reset_index(inplace=True)
df_stats_H1_08['high2high'] = df_stats_H1_08['high'] - df_stats_H1_812['high']
df_stats_H1_08['low2low'] = df_stats_H1_08['low'] - df_stats_H1_812['low']
...
if __name__ == "__main__":
main()
Das sieht gut aus, teste ich später.Sirius3 hat geschrieben: ↑Dienstag 3. Oktober 2023, 13:18 Jetzt hast Du ja immer noch for-Schleifen obwohl Du ja schon die passenden Filter definiert hast. Warum?
Was soll auch diese komische if-Bedingungen, mit denen Du low und high auf 0 bis 1000 einschränkst? Ist das wirklich die beabsichtigte Wirkung?
Hast Du wirklich exakt gleich viele Elemente von 0 bis 8 Uhr wie von 8 bis 12 Uhr? Weil sonst funktioniert ja die Differenzbildung nicht. Und was soll das überhaupt bedeuten, einen Wert von irgendwann zwischen 0 und 8 von einem beliebigen zwischen 8 und 12 abzuziehen?
Von Deinem Code bleibt also nicht mehr viel übrig, weil man mit Pandas solche Operationen sehr kompakt schreiben kann:Code: Alles auswählen
def read_data(): try: selected=mt5.symbol_select("EURUSD",True) if not selected: raise RuntimeError("failed to select symbol") timezone = pytz.timezone("Etc/UTC") utc_from = datetime(2023, 1, 1, tzinfo=timezone) utc_to = datetime(2023, 10, 3, tzinfo=timezone) rates_H1 = mt5.copy_rates_range("EURUSD", mt5.TIMEFRAME_H1, utc_from, utc_to) finally: mt5.shutdown() return rates_H1 def main(): ... df_H1 = pd.DataFrame(read_data()) df_H1['time']=pd.to_datetime(df_H1['time'], unit='s') df_H1['low'] = df_H1['low'].clip_upper(1000) df_H1['high'] = df_H1['high'].clip_lower(0) filter08 = df_H1.time.dt.hour.between(0, 8, 'both') filter812 = df_H1.time.dt.hour.between(8, 12, 'both') df_stats_H1_08 = df_H1[filter08] df_stats_H1_812 = df_H1[filter812] df_stats_H1_08.reset_index(inplace=True) df_stats_H1_812.reset_index(inplace=True) df_stats_H1_08['high2high'] = df_stats_H1_08['high'] - df_stats_H1_812['high'] df_stats_H1_08['low2low'] = df_stats_H1_08['low'] - df_stats_H1_812['low'] ... if __name__ == "__main__": main()
Ich schränke low und high nicht auf 0 und 1000 ein, das sind lediglich Werte, um sicherzustellen, dass die if conditions ziehen, weil die Kurse werden >0 und <1000 sein.
Ja, es werden exakt gleich viel Elemente sein, für jede Stunde genau eins; meine Differenzbildung funktioniert ja.
Mit dem Abziehen des einen Werts vom anderen überprüfe ich, ob in den Stunden von 8-12 der Kurs zum Hoch der Stunden von 0-8 zurück kam.
Das versuche ich gerade ungefähr so zu checken, dass mir hierzu "ja" und "nein" in eine weitere Spalte "back2high08" geschrieben wird:
Code: Alles auswählen
df_stats_H1_08['back2high08'] = df_stats_H1_08[['high08', 'low812']].apply(lambda x: 'ja' if df_stats_H1_08['low812'] <= df_stats_H1_08['high08'] else 'nein')
Ich finde keine Beispiele für eine lambda Funktion mit einer Condition, die abhängig von SpaltenValues ist.
Update: Die Funktion habe ich hinbekommen:ChrisLi hat geschrieben: ↑Dienstag 3. Oktober 2023, 16:35Das sieht gut aus, teste ich später.Sirius3 hat geschrieben: ↑Dienstag 3. Oktober 2023, 13:18 Jetzt hast Du ja immer noch for-Schleifen obwohl Du ja schon die passenden Filter definiert hast. Warum?
Was soll auch diese komische if-Bedingungen, mit denen Du low und high auf 0 bis 1000 einschränkst? Ist das wirklich die beabsichtigte Wirkung?
Hast Du wirklich exakt gleich viele Elemente von 0 bis 8 Uhr wie von 8 bis 12 Uhr? Weil sonst funktioniert ja die Differenzbildung nicht. Und was soll das überhaupt bedeuten, einen Wert von irgendwann zwischen 0 und 8 von einem beliebigen zwischen 8 und 12 abzuziehen?
Von Deinem Code bleibt also nicht mehr viel übrig, weil man mit Pandas solche Operationen sehr kompakt schreiben kann:Code: Alles auswählen
def read_data(): try: selected=mt5.symbol_select("EURUSD",True) if not selected: raise RuntimeError("failed to select symbol") timezone = pytz.timezone("Etc/UTC") utc_from = datetime(2023, 1, 1, tzinfo=timezone) utc_to = datetime(2023, 10, 3, tzinfo=timezone) rates_H1 = mt5.copy_rates_range("EURUSD", mt5.TIMEFRAME_H1, utc_from, utc_to) finally: mt5.shutdown() return rates_H1 def main(): ... df_H1 = pd.DataFrame(read_data()) df_H1['time']=pd.to_datetime(df_H1['time'], unit='s') df_H1['low'] = df_H1['low'].clip_upper(1000) df_H1['high'] = df_H1['high'].clip_lower(0) filter08 = df_H1.time.dt.hour.between(0, 8, 'both') filter812 = df_H1.time.dt.hour.between(8, 12, 'both') df_stats_H1_08 = df_H1[filter08] df_stats_H1_812 = df_H1[filter812] df_stats_H1_08.reset_index(inplace=True) df_stats_H1_812.reset_index(inplace=True) df_stats_H1_08['high2high'] = df_stats_H1_08['high'] - df_stats_H1_812['high'] df_stats_H1_08['low2low'] = df_stats_H1_08['low'] - df_stats_H1_812['low'] ... if __name__ == "__main__": main()
Ich schränke low und high nicht auf 0 und 1000 ein, das sind lediglich Werte, um sicherzustellen, dass die if conditions ziehen, weil die Kurse werden >0 und <1000 sein.
Ja, es werden exakt gleich viel Elemente sein, für jede Stunde genau eins; meine Differenzbildung funktioniert ja.
Mit dem Abziehen des einen Werts vom anderen überprüfe ich, ob in den Stunden von 8-12 der Kurs zum Hoch der Stunden von 0-8 zurück kam.
Das versuche ich gerade ungefähr so zu checken, dass mir hierzu "ja" und "nein" in eine weitere Spalte "back2high08" geschrieben wird:
Aber das will noch nicht..Code: Alles auswählen
df_stats_H1_08['back2high08'] = df_stats_H1_08[['high08', 'low812']].apply(lambda x: 'ja' if df_stats_H1_08['low812'] <= df_stats_H1_08['high08'] else 'nein')
Ich finde keine Beispiele für eine lambda Funktion mit einer Condition, die abhängig von SpaltenValues ist.
Code: Alles auswählen
df_stats_H1_08['back2high08'] = df_stats_H1_08[['high08', 'low812']].apply(lambda row: True if (row['low812'] <= row['high08']) else False, axis=1)
Oder einfach:
Code: Alles auswählen
df_stats_H1_08['back2high08'] = df_stats_H1_08['low812'] <= df_stats_H1_08['high08']
ChrisLi hat geschrieben: ↑Dienstag 3. Oktober 2023, 16:35Das mit dem clip_upper/lower ist zu früh angewendet; es gilt (wenn es überhaupt das richtige ist..) für die Werte, die nach filter08 und filter812 übrigbleiben; aber das mag hinfällig sein, wenn folgendes ggf. ohne möglich ist, weil die 0 und die 1000 brauchte ich für meinen Schleifenunsinn, mit dem ich nun ans Ende der Möglichkeiten gekommen bin.Sirius3 hat geschrieben: ↑Dienstag 3. Oktober 2023, 13:18 Jetzt hast Du ja immer noch for-Schleifen obwohl Du ja schon die passenden Filter definiert hast. Warum?
Was soll auch diese komische if-Bedingungen, mit denen Du low und high auf 0 bis 1000 einschränkst? Ist das wirklich die beabsichtigte Wirkung?
Hast Du wirklich exakt gleich viele Elemente von 0 bis 8 Uhr wie von 8 bis 12 Uhr? Weil sonst funktioniert ja die Differenzbildung nicht. Und was soll das überhaupt bedeuten, einen Wert von irgendwann zwischen 0 und 8 von einem beliebigen zwischen 8 und 12 abzuziehen?
Von Deinem Code bleibt also nicht mehr viel übrig, weil man mit Pandas solche Operationen sehr kompakt schreiben kann:Code: Alles auswählen
def read_data(): try: selected=mt5.symbol_select("EURUSD",True) if not selected: raise RuntimeError("failed to select symbol") timezone = pytz.timezone("Etc/UTC") utc_from = datetime(2023, 1, 1, tzinfo=timezone) utc_to = datetime(2023, 10, 3, tzinfo=timezone) rates_H1 = mt5.copy_rates_range("EURUSD", mt5.TIMEFRAME_H1, utc_from, utc_to) finally: mt5.shutdown() return rates_H1 def main(): ... df_H1 = pd.DataFrame(read_data()) df_H1['time']=pd.to_datetime(df_H1['time'], unit='s') df_H1['low'] = df_H1['low'].clip_upper(1000) df_H1['high'] = df_H1['high'].clip_lower(0) filter08 = df_H1.time.dt.hour.between(0, 8, 'both') filter812 = df_H1.time.dt.hour.between(8, 12, 'both') df_stats_H1_08 = df_H1[filter08] df_stats_H1_812 = df_H1[filter812] df_stats_H1_08.reset_index(inplace=True) df_stats_H1_812.reset_index(inplace=True) df_stats_H1_08['high2high'] = df_stats_H1_08['high'] - df_stats_H1_812['high'] df_stats_H1_08['low2low'] = df_stats_H1_08['low'] - df_stats_H1_812['low'] ... if __name__ == "__main__": main()
Es geht um die Werte, die der filter812 filtert. In den Stunden 8 - 12:oo haben wir ein high und ein low, die brauche ich; weiter müssen dann die time.hours von den beiden verglichen werden und nur die kommen durch, wo das low.time.hour > high.time.hour liegt, wo das low also nach dem high kam.
Nochmal in kurz:
1. high812 muss > high08 sein
2. low812 muss zeitlich nach high812 kommen (low812.time.hour > high812.time.hour)
Hier ein Bspw. wie der df aussieht:
1. Das high08 (0-8:00) (Broker fängt um 1:oo an) ist 13560.38 und das high812 13596.00; Ist das high812 > das high08, dann weiter bei 2, sonst weg.Code: Alles auswählen
time open high low close vol spread real_vol 502 2021-02-03 01:00:00 13519.12 13520.75 13494.62 13499.88 3328 200 0 503 2021-02-03 02:00:00 13499.88 13545.12 13487.88 13539.38 4733 200 0 504 2021-02-03 03:00:00 13539.75 13540.00 13505.38 13522.62 5553 200 0 505 2021-02-03 04:00:00 13522.38 13534.88 13502.12 13523.88 4741 200 0 506 2021-02-03 05:00:00 13523.50 13525.12 13512.12 13520.25 2823 200 0 507 2021-02-03 06:00:00 13520.12 13538.62 13518.25 13529.00 2241 200 0 508 2021-02-03 07:00:00 13528.75 13558.25 13525.12 13556.62 3033 200 0 509 2021-02-03 08:00:00 13556.38 13560.38 13549.00 13558.12 2002 100 0 510 2021-02-03 09:00:00 13557.88 13591.62 13550.38 13589.12 3836 100 0 511 2021-02-03 10:00:00 13588.88 13596.00 13558.25 13561.75 7818 100 0 512 2021-02-03 11:00:00 13561.62 13566.12 13526.00 13531.62 6442 100 0 513 2021-02-03 12:00:00 13531.88 13562.88 13529.88 13554.88 5241 100 0
2. Wir haben das high812 von 13596.00 und low812 von 13526.00 ; das low kommt um 11:oo nach dem high um 10:oo, also will ich die beiden haben.
Wäre das low um 10:oo und das high um 11:oo gewesen, hätte der Filter es verwerfen sollen.