This commit is contained in:
Binary file not shown.
@@ -133,32 +133,31 @@ class GettexExchange(BaseExchange):
|
||||
with gzip.GzipFile(fileobj=io.BytesIO(response.content)) as f:
|
||||
csv_text = f.read().decode('utf-8')
|
||||
|
||||
# Debug: Zeige erste Zeilen und Spalten
|
||||
lines = csv_text.strip().split('\n')
|
||||
if lines:
|
||||
print(f"[GETTEX] CSV has {len(lines)} lines, first line (headers): {lines[0][:200]}")
|
||||
if len(lines) > 1:
|
||||
print(f"[GETTEX] Sample data row: {lines[1][:200]}")
|
||||
if not lines:
|
||||
return []
|
||||
|
||||
# CSV parsen - versuche verschiedene Delimiter
|
||||
delimiter = ';' if ';' in lines[0] else ','
|
||||
reader = csv.DictReader(io.StringIO(csv_text), delimiter=delimiter)
|
||||
# Extrahiere Datum aus Dateinamen (Format: posttrade.YYYYMMDD.HH.MM.xxx.csv.gz)
|
||||
date_str = None
|
||||
parts = filename.split('.')
|
||||
if len(parts) >= 4:
|
||||
date_str = parts[1] # YYYYMMDD
|
||||
|
||||
row_count = 0
|
||||
for row in reader:
|
||||
row_count += 1
|
||||
if row_count == 1:
|
||||
print(f"[GETTEX] CSV columns: {list(row.keys())}")
|
||||
# Gettex CSV hat KEINEN Header!
|
||||
# Format: ISIN,Zeit,Währung,Preis,Menge
|
||||
# z.B.: DE000BAY0017,09:15:03.638460,EUR,45.775,22
|
||||
for line in lines:
|
||||
if not line.strip():
|
||||
continue
|
||||
try:
|
||||
trade = self._parse_csv_row(row)
|
||||
trade = self._parse_headerless_csv_line(line, date_str)
|
||||
if trade:
|
||||
trades.append(trade)
|
||||
except Exception as e:
|
||||
if row_count <= 3:
|
||||
print(f"[GETTEX] Error parsing row {row_count}: {e}, row keys: {list(row.keys())}")
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
print(f"[GETTEX] Processed {row_count} rows, found {len(trades)} valid trades")
|
||||
if trades:
|
||||
print(f"[GETTEX] Parsed {len(trades)} trades from {filename}")
|
||||
|
||||
except requests.exceptions.HTTPError as e:
|
||||
if e.response.status_code != 404:
|
||||
@@ -168,6 +167,69 @@ class GettexExchange(BaseExchange):
|
||||
|
||||
return trades
|
||||
|
||||
def _parse_headerless_csv_line(self, line: str, date_str: str = None) -> Optional[Trade]:
|
||||
"""
|
||||
Parst eine headerlose CSV-Zeile im gettex Format.
|
||||
Format: ISIN,Zeit,Währung,Preis,Menge
|
||||
z.B.: DE000BAY0017,09:15:03.638460,EUR,45.775,22
|
||||
"""
|
||||
try:
|
||||
parts = line.strip().split(',')
|
||||
if len(parts) < 5:
|
||||
return None
|
||||
|
||||
isin = parts[0].strip()
|
||||
time_str = parts[1].strip()
|
||||
# currency = parts[2].strip() # nicht benötigt
|
||||
price_str = parts[3].strip()
|
||||
qty_str = parts[4].strip()
|
||||
|
||||
# Validierung
|
||||
if not isin or len(isin) != 12: # ISIN ist immer 12 Zeichen
|
||||
return None
|
||||
|
||||
price = float(price_str)
|
||||
quantity = float(qty_str)
|
||||
|
||||
if price <= 0 or quantity <= 0:
|
||||
return None
|
||||
|
||||
# Timestamp bauen
|
||||
# date_str ist YYYYMMDD, time_str ist HH:MM:SS.ffffff
|
||||
if date_str and len(date_str) == 8:
|
||||
year = date_str[:4]
|
||||
month = date_str[4:6]
|
||||
day = date_str[6:8]
|
||||
date_part = f"{year}-{month}-{day}"
|
||||
else:
|
||||
# Fallback: heute
|
||||
date_part = datetime.now(timezone.utc).strftime('%Y-%m-%d')
|
||||
|
||||
# Zeit parsen (z.B. 09:15:03.638460)
|
||||
ts_str = f"{date_part}T{time_str}"
|
||||
|
||||
# Mikrosekunden kürzen wenn zu lang
|
||||
if '.' in ts_str:
|
||||
base, frac = ts_str.rsplit('.', 1)
|
||||
if len(frac) > 6:
|
||||
frac = frac[:6]
|
||||
ts_str = f"{base}.{frac}"
|
||||
|
||||
timestamp = datetime.fromisoformat(ts_str)
|
||||
timestamp = timestamp.replace(tzinfo=timezone.utc)
|
||||
|
||||
return Trade(
|
||||
exchange=self.name,
|
||||
symbol=isin,
|
||||
isin=isin,
|
||||
price=price,
|
||||
quantity=quantity,
|
||||
timestamp=timestamp
|
||||
)
|
||||
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _parse_csv_row(self, row: dict) -> Optional[Trade]:
|
||||
"""
|
||||
Parst eine CSV-Zeile zu einem Trade.
|
||||
@@ -390,29 +452,30 @@ class GettexExchange(BaseExchange):
|
||||
with gzip.GzipFile(fileobj=io.BytesIO(response.content)) as f:
|
||||
csv_text = f.read().decode('utf-8')
|
||||
|
||||
# Debug: Zeige erste Zeilen
|
||||
lines = csv_text.strip().split('\n')
|
||||
if len(lines) <= 1:
|
||||
# Datei ist leer oder nur Header
|
||||
if not lines:
|
||||
return []
|
||||
|
||||
# CSV parsen - versuche verschiedene Delimiter
|
||||
delimiter = ';' if ';' in lines[0] else (',' if ',' in lines[0] else '\t')
|
||||
reader = csv.DictReader(io.StringIO(csv_text), delimiter=delimiter)
|
||||
# Extrahiere Datum aus Dateinamen (Format: posttrade.YYYYMMDD.HH.MM.xxx.csv.gz)
|
||||
date_str = None
|
||||
parts = filename.split('.')
|
||||
if len(parts) >= 4:
|
||||
date_str = parts[1] # YYYYMMDD
|
||||
|
||||
row_count = 0
|
||||
for row in reader:
|
||||
row_count += 1
|
||||
# Gettex CSV hat KEINEN Header!
|
||||
# Format: ISIN,Zeit,Währung,Preis,Menge
|
||||
for line in lines:
|
||||
if not line.strip():
|
||||
continue
|
||||
try:
|
||||
trade = self._parse_csv_row(row)
|
||||
trade = self._parse_headerless_csv_line(line, date_str)
|
||||
if trade:
|
||||
trades.append(trade)
|
||||
except Exception as e:
|
||||
if row_count <= 2:
|
||||
print(f"[{self.name}] Error parsing row: {e}, keys: {list(row.keys())[:5]}")
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
print(f"[{self.name}] Parsed {len(trades)} trades from {filename}")
|
||||
if trades:
|
||||
print(f"[{self.name}] Parsed {len(trades)} trades from {filename}")
|
||||
|
||||
except requests.exceptions.HTTPError as e:
|
||||
if e.response.status_code != 404:
|
||||
|
||||
Reference in New Issue
Block a user