IndexError: single positional indexer is out-of-bounds

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
ChrisLi
User
Beiträge: 17
Registriert: Dienstag 26. September 2023, 23:06

Hallo,

ich ziehe mir Daten vom Broker, filter mir diese nach den Stunden 8:oo - 20:oo, berechne von jedem 13-Stunden-Block max, min, idxmax und idxmin und brauche dann für die spätere Arbeit alle dates von den rows/Stunden des kleinsten Wertes/Kurses.

Ich kann leider kein csv dranhängen, Attachments werden hier nicht unterstützt? Wenn ich nur einen kurzen Zeitraum über ein paar Tage wähle, läuft es durch; es passiert erst nach hunderten von Zeilen.

Hier kommt nach einigen Tausend rows der bekannte "IndexError: single positional indexer is out-of-bounds", aber es ist nichts out-of-bounds. Das Problem liegt in der 4rt-letzten Zeile:

Code: Alles auswählen

        the_date = df_820.query('index=={}'.format(valmin))['time'].dt.date.iloc[0]

Code: Alles auswählen

NOK, low-hr < high.hr
the_date:  2023-07-24
NOK, low-hr < high.hr
Traceback (most recent call last):
  File "c:/Users/moneyKI/Documents/PyAnalytics/bsc/ustec_indexoutofrange_shorter.py", line 91, in <module>
    the_date = df_820.query('index=={}'.format(valmin))['time'].dt.date.iloc[0]
  File "C:\ProgramData\Anaconda3\envs\Py38\lib\site-packages\pandas\core\indexing.py", line 1073, in __getitem__
    return self._getitem_axis(maybe_callable, axis=axis)
  File "C:\ProgramData\Anaconda3\envs\Py38\lib\site-packages\pandas\core\indexing.py", line 1625, in _getitem_axis
    self._validate_integer(key, axis)
  File "C:\ProgramData\Anaconda3\envs\Py38\lib\site-packages\pandas\core\indexing.py", line 1557, in _validate_integer
    raise IndexError("single positional indexer is out-of-bounds")
IndexError: single positional indexer is out-of-bounds
PS C:\Users\moneyKI\Documents\PyAnalytics> 

Man kann sich den dataframe ansehen und ich kann das Problem nicht nachvollziehen. Dazu, wenn ich den Zeitraum ändere, läuft es manchmal durch oder stockt an einer anderen Stelle.
Ich verstehe es halt leider nicht.


Hier der Code:

Code: Alles auswählen

import MetaTrader5 as mt5
import pandas as pd
import numpy as np
import pytz
from datetime import datetime
from datetime import timedelta
import time

pd.set_option('display.max_rows', None)
pd.options.display.width = None

# establish connection to MetaTrader 5 terminal
if not mt5.initialize():
    print("initialize() failed, error code =",mt5.last_error())
    quit()

account = your account 
authorized = mt5.login(account, password="yourPW", server="yourServer)

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("USDJPY",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(2022, 1, 1, tzinfo=timezone)
utc_to = datetime(2023, 10, 17, 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)

# write df to csv
df_H1.to_csv('~/df_H1.csv', index=False, sep='\t', encoding='utf-8', header=True, float_format='%.3f')

# convert time in seconds into the datetime format
df_H1['time']=pd.to_datetime(df_H1['time'], unit='s')
df_H1_hl = df_H1[["time", "high", "low"]]

# 1. get 8:oo-20:oo 
filter820 = df_H1.time.dt.hour.between(8, 20, 'both')
df_820 = df_H1_hl[filter820]

# 2. get max, maxindex, min and minindex of each 8-20 period
n = 13 # 8:oo-20:oo = 13hrs/rows
max820 = df_820.groupby(np.arange(len(df_820))//n)['high'].max()
list_idxmax = df_820.groupby(np.arange(len(df_820))//n)['high'].idxmax()
min820 = df_820.groupby(np.arange(len(df_820))//n)['low'].min()
list_idxmin = df_820.groupby(np.arange(len(df_820))//n)['low'].idxmin()

df_820.reset_index(inplace=True)

# making copy of df_820 in which matched rows are deleted
df_result = df_820

# Taking indizes from max-/min-values to find the time/hr of the max/min values
for i in range(len(list_idxmax)):
    valmax = list_idxmax[i]
    valmin = list_idxmin[i]
    if valmin > valmax:
        print("OK, low.hr > high.hr")
    else:
        print("NOK, low-hr < high.hr")
        the_date = df_820.query('index=={}'.format(valmin))['time'].dt.date.iloc[0]
        print("the_date it fails: ", the_date)
        df_tmp = df_820[df_820.time.dt.date == the_date]
        df_result.drop(df_tmp.index, axis=0, inplace=True)

Der df hat ein wie üblich stabiles Format:

Code: Alles auswählen

time	high	low
2022-01-03 08:00:00	1.135	1.134
2022-01-03 09:00:00	1.135	1.133
2022-01-03 10:00:00	1.135	1.134
2022-01-03 11:00:00	1.136	1.134
2022-01-03 12:00:00	1.136	1.135
2022-01-03 13:00:00	1.137	1.135
2022-01-03 14:00:00	1.136	1.135
2022-01-03 15:00:00	1.136	1.135
2022-01-03 16:00:00	1.135	1.130
2022-01-03 17:00:00	1.131	1.129
2022-01-03 18:00:00	1.130	1.128
2022-01-03 19:00:00	1.129	1.128
2022-01-03 20:00:00	1.130	1.128
2022-01-04 08:00:00	1.131	1.129
2022-01-04 09:00:00	1.129	1.128
2022-01-04 10:00:00	1.130	1.129
2022-01-04 11:00:00	1.131	1.128
2022-01-04 12:00:00	1.131	1.129
2022-01-04 13:00:00	1.130	1.128
2022-01-04 14:00:00	1.128	1.127
2022-01-04 15:00:00	1.129	1.127
2022-01-04 16:00:00	1.129	1.128
2022-01-04 17:00:00	1.132	1.128
2022-01-04 18:00:00	1.132	1.129
2022-01-04 19:00:00	1.130	1.129
2022-01-04 20:00:00	1.129	1.128
2022-01-05 08:00:00	1.130	1.129
2022-01-05 09:00:00	1.130	1.129
2022-01-05 10:00:00	1.131	1.130
2022-01-05 11:00:00	1.131	1.130
2022-01-05 12:00:00	1.131	1.130
2022-01-05 13:00:00	1.132	1.131
2022-01-05 14:00:00	1.133	1.130
2022-01-05 15:00:00	1.133	1.130
Da fehlt nirgends was und ist auch, soweit ich das sehe, nichts out of bounds.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Dein Code wird immer länger, aber Struktur hat er immer weniger. Fang endlich an sinnvolle Funktionen zu definieren. Ich glaube kaum dass hier jemand Lust hat, sich durch diesen Spaghetti-Code durchzuquälen.
Über ein Index iteriert man nicht. Stattdessen könnte man zip verwenden.
df_result und df_820 sind das identische Objekt. Du löschst also aus diesem Objekt Seilen und wunderst dich dass die Indizes nicht mehr passen?!
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Um das noch mal deutlicher zu machen: Der Kommentar hier stimmt nicht, da wird nix kopiert.

Code: Alles auswählen

# making copy of df_820 in which matched rows are deleted
df_result = df_820
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten