This commit is contained in:
@@ -133,17 +133,32 @@ class GettexExchange(BaseExchange):
|
||||
with gzip.GzipFile(fileobj=io.BytesIO(response.content)) as f:
|
||||
csv_text = f.read().decode('utf-8')
|
||||
|
||||
# CSV parsen
|
||||
reader = csv.DictReader(io.StringIO(csv_text), delimiter=';')
|
||||
# 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]}")
|
||||
|
||||
# CSV parsen - versuche verschiedene Delimiter
|
||||
delimiter = ';' if ';' in lines[0] else ','
|
||||
reader = csv.DictReader(io.StringIO(csv_text), delimiter=delimiter)
|
||||
|
||||
row_count = 0
|
||||
for row in reader:
|
||||
row_count += 1
|
||||
if row_count == 1:
|
||||
print(f"[GETTEX] CSV columns: {list(row.keys())}")
|
||||
try:
|
||||
trade = self._parse_csv_row(row)
|
||||
if trade:
|
||||
trades.append(trade)
|
||||
except Exception as e:
|
||||
print(f"[GETTEX] Error parsing row: {e}")
|
||||
if row_count <= 3:
|
||||
print(f"[GETTEX] Error parsing row {row_count}: {e}, row keys: {list(row.keys())}")
|
||||
continue
|
||||
|
||||
print(f"[GETTEX] Processed {row_count} rows, found {len(trades)} valid trades")
|
||||
|
||||
except requests.exceptions.HTTPError as e:
|
||||
if e.response.status_code != 404:
|
||||
@@ -157,48 +172,102 @@ class GettexExchange(BaseExchange):
|
||||
"""
|
||||
Parst eine CSV-Zeile zu einem Trade.
|
||||
|
||||
Erwartete Spalten (RTS Format):
|
||||
- TrdDtTm: Trading Date/Time
|
||||
- ISIN: Instrument Identifier
|
||||
- Pric: Preis
|
||||
- Qty: Menge
|
||||
- Ccy: Währung
|
||||
Unterstützte Spalten (RTS1/RTS2 Format, verschiedene Varianten):
|
||||
- ISIN / FinInstrmId / Isin: Instrument Identifier
|
||||
- Pric / Price / pric: Preis
|
||||
- Qty / Quantity / qty: Menge
|
||||
- TrdDtTm / TradingDateTime / TrdgDtTm: Trading Date/Time
|
||||
- TrdDt / TradingDate: Trading Date
|
||||
- TrdTm / TradingTime: Trading Time
|
||||
"""
|
||||
try:
|
||||
# ISIN
|
||||
isin = row.get('ISIN', row.get('FinInstrmId', ''))
|
||||
# ISIN - versuche verschiedene Spaltennamen
|
||||
isin = None
|
||||
for key in ['ISIN', 'Isin', 'isin', 'FinInstrmId', 'FinInstrmId.Id', 'Id']:
|
||||
if key in row and row[key]:
|
||||
isin = str(row[key]).strip()
|
||||
break
|
||||
|
||||
if not isin:
|
||||
return None
|
||||
|
||||
# Preis
|
||||
price_str = row.get('Pric', row.get('Price', '0'))
|
||||
price_str = price_str.replace(',', '.')
|
||||
price = float(price_str)
|
||||
# Preis - versuche verschiedene Spaltennamen
|
||||
price = None
|
||||
for key in ['Pric', 'Price', 'pric', 'price', 'Pric.Pric.MntryVal.Amt', 'TradPric']:
|
||||
if key in row and row[key]:
|
||||
price_str = str(row[key]).replace(',', '.').strip()
|
||||
try:
|
||||
price = float(price_str)
|
||||
if price > 0:
|
||||
break
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
if price <= 0:
|
||||
if not price or price <= 0:
|
||||
return None
|
||||
|
||||
# Menge
|
||||
qty_str = row.get('Qty', row.get('Quantity', '0'))
|
||||
qty_str = qty_str.replace(',', '.')
|
||||
quantity = float(qty_str)
|
||||
# Menge - versuche verschiedene Spaltennamen
|
||||
quantity = None
|
||||
for key in ['Qty', 'Quantity', 'qty', 'quantity', 'TradQty', 'Qty.Unit']:
|
||||
if key in row and row[key]:
|
||||
qty_str = str(row[key]).replace(',', '.').strip()
|
||||
try:
|
||||
quantity = float(qty_str)
|
||||
if quantity > 0:
|
||||
break
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
if quantity <= 0:
|
||||
if not quantity or quantity <= 0:
|
||||
return None
|
||||
|
||||
# Timestamp
|
||||
ts_str = row.get('TrdDtTm', row.get('TradingDateTime', ''))
|
||||
# Timestamp - versuche verschiedene Formate
|
||||
ts_str = None
|
||||
|
||||
# Erst kombiniertes Feld versuchen
|
||||
for key in ['TrdDtTm', 'TradingDateTime', 'TrdgDtTm', 'Timestamp', 'timestamp']:
|
||||
if key in row and row[key]:
|
||||
ts_str = str(row[key]).strip()
|
||||
break
|
||||
|
||||
# Falls nicht gefunden, separate Felder kombinieren
|
||||
if not ts_str:
|
||||
# Fallback: Separate Felder
|
||||
trd_dt = row.get('TrdDt', '')
|
||||
trd_tm = row.get('TrdTm', '00:00:00')
|
||||
ts_str = f"{trd_dt}T{trd_tm}"
|
||||
trd_dt = None
|
||||
trd_tm = '00:00:00'
|
||||
|
||||
for key in ['TrdDt', 'TradingDate', 'Date', 'date']:
|
||||
if key in row and row[key]:
|
||||
trd_dt = str(row[key]).strip()
|
||||
break
|
||||
|
||||
for key in ['TrdTm', 'TradingTime', 'Time', 'time']:
|
||||
if key in row and row[key]:
|
||||
trd_tm = str(row[key]).strip()
|
||||
break
|
||||
|
||||
if trd_dt:
|
||||
ts_str = f"{trd_dt}T{trd_tm}"
|
||||
|
||||
if not ts_str:
|
||||
return None
|
||||
|
||||
# Parse Timestamp (UTC)
|
||||
ts_str = ts_str.replace('Z', '+00:00')
|
||||
if 'T' not in ts_str:
|
||||
ts_str = ts_str.replace(' ', 'T')
|
||||
|
||||
# Entferne Mikrosekunden wenn zu lang
|
||||
if '.' in ts_str:
|
||||
parts = ts_str.split('.')
|
||||
if len(parts) > 1:
|
||||
ms_part = parts[1].split('+')[0].split('-')[0]
|
||||
if len(ms_part) > 6:
|
||||
ts_str = parts[0] + '.' + ms_part[:6]
|
||||
if '+' in parts[1]:
|
||||
ts_str += '+' + parts[1].split('+')[1]
|
||||
elif '-' in parts[1][1:]:
|
||||
ts_str += '-' + parts[1].split('-')[-1]
|
||||
|
||||
timestamp = datetime.fromisoformat(ts_str)
|
||||
if timestamp.tzinfo is None:
|
||||
timestamp = timestamp.replace(tzinfo=timezone.utc)
|
||||
@@ -213,7 +282,7 @@ class GettexExchange(BaseExchange):
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[GETTEX] Error parsing CSV row: {e}")
|
||||
# Nur bei den ersten paar Fehlern loggen
|
||||
return None
|
||||
|
||||
def fetch_latest_trades(self, include_yesterday: bool = True, since_date: datetime = None) -> List[Trade]:
|
||||
@@ -289,7 +358,6 @@ class GettexExchange(BaseExchange):
|
||||
trades = []
|
||||
|
||||
try:
|
||||
print(f"[{self.name}] Downloading: {url}")
|
||||
response = requests.get(url, headers=HEADERS, timeout=60)
|
||||
|
||||
if response.status_code == 404:
|
||||
@@ -301,16 +369,26 @@ class GettexExchange(BaseExchange):
|
||||
with gzip.GzipFile(fileobj=io.BytesIO(response.content)) as f:
|
||||
csv_text = f.read().decode('utf-8')
|
||||
|
||||
# CSV parsen
|
||||
reader = csv.DictReader(io.StringIO(csv_text), delimiter=';')
|
||||
# Debug: Zeige erste Zeilen
|
||||
lines = csv_text.strip().split('\n')
|
||||
if len(lines) <= 1:
|
||||
# Datei ist leer oder nur Header
|
||||
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)
|
||||
|
||||
row_count = 0
|
||||
for row in reader:
|
||||
row_count += 1
|
||||
try:
|
||||
trade = self._parse_csv_row(row)
|
||||
if trade:
|
||||
trades.append(trade)
|
||||
except Exception as e:
|
||||
print(f"[{self.name}] Error parsing row: {e}")
|
||||
if row_count <= 2:
|
||||
print(f"[{self.name}] Error parsing row: {e}, keys: {list(row.keys())[:5]}")
|
||||
continue
|
||||
|
||||
print(f"[{self.name}] Parsed {len(trades)} trades from {filename}")
|
||||
|
||||
Reference in New Issue
Block a user