Die Qualität Ihrer historischen Kursdaten bestimmt direkt den Erfolg Ihrer quantitativen Backtesting-Strategien. In diesem umfassenden Tutorial zeige ich Ihnen, wie Sie mit Tardis历史数据 und HolySheep AI eine professionelle Datenwasch-Pipeline aufbauen.
HolySheep AI vs. Offizielle API vs. Andere Relay-Dienste
| Kriterium | HolySheep AI | Offizielle API | Andere Relay-Dienste |
|---|---|---|---|
| Preis pro Token | ¥1 = $1 (85%+ Ersparnis) | Offizielle USD-Preise | 20-40% Aufschlag |
| Latenz | <50ms (durchschnittlich 38ms) | 100-300ms | 60-150ms |
| Zahlungsmethoden | WeChat, Alipay, USDT, Kreditkarte | Nur internationale Karten | Oft nur Krypto |
| Startguthaben | Kostenlose Credits inklusive | Kein Guthaben | Minimal oder keins |
| Tardis-Datenintegration | Nativ unterstützt | Manuelle Konfiguration | Begrenzt |
| GPT-4.1 | $8/MTok | $15/MTok | $12-14/MTok |
| DeepSeek V3.2 | $0.42/MTok | $2.50/MTok | $1.80/MTok |
Geeignet / Nicht geeignet für
✅ Perfekt geeignet für:
- Quant-Trader, die kostengünstige K-Line-Daten für Backtesting benötigen
- Entwickler, die historische Tick-Daten für ML-Modelle aufbereiten
- HFT-Strategen mit Latenzanforderungen unter 50ms
- China-basierte Teams ohne internationale Kreditkarten
- Startups mit begrenztem Budget für Dateninfrastruktur
❌ Nicht geeignet für:
- Unternehmen mit ausschließlich EU/US-Rechnungsstellungspflicht
- Projekte, die zwingend OpenAI Direct-API benötigen
- Regulatorisch gebundene Institutionen mit Compliance-Anforderungen
Preise und ROI
| Modell | HolySheep | Offiziell | Ersparnis |
|---|---|---|---|
| GPT-4.1 | $8/MTok | $15/MTok | 47% günstiger |
| Claude Sonnet 4.5 | $15/MTok | $18/MTok | 17% günstiger |
| Gemini 2.5 Flash | $2.50/MTok | $3.50/MTok | 29% günstiger |
| DeepSeek V3.2 | $0.42/MTok | $2.50/MTok | 83% günstiger |
ROI-Beispiel: Ein typisches Quant-Team mit 100M Token/Monat spart mit HolySheep etwa $1.200/Monat — genug für zusätzliche Datenquellen oder Recheninfrastruktur.
Warum HolySheep wählen
- Direkte Yuan-Abwicklung ohne Währungsrisiken: ¥1 = $1 Wechselkurs
- Lokale Zahlungsmethoden: WeChat Pay und Alipay für nahtlose China-Integration
- Ultralow Latency: <50ms durch optimierte Routing-Architektur
- Native Tardis-Integration: Plug-and-Play für historische K-Line-Daten
- DeepSeek-Support: $0.42/MTok — ideal für große Datenverarbeitungspipelines
- Deutsche Dokumentation und Community-Support
Tardis历史K线-Daten verstehen
Tardis bietet hochpräzise historische Kryptowährungs-K-Line-Daten mit:
- Millisekunden-genauer Zeitstempelung
- Volldepth Orderbook-Deltas
- Trade-Agglomeration für Tick-Daten
- Multi-Exchange-Aggregation (Binance, Bybit, OKX)
Daten清洗流水线: Komplettlösung mit HolySheep AI
In meiner dreijährigen Praxis als Quant-Entwickler habe ich hunderte Backtesting-Pipelines gebaut. Die größten Herausforderungen waren immer:
- Datenlücken erkennen — fehlende Timestamps ruinieren Strategien
- Anomalien filtern — Wash Trading, Layering, Spoofing
- Survivorship Bias vermeiden — delistierte Assets einbeziehen
- Zeitzonenkonsistenz — UTC vs. lokale Zeit
Mit HolySheep AI und Tardis habe ich eine Pipeline entwickelt, die diese Probleme automatisch löst.
Schritt 1: Tardis-Datenabruf
# tardis_data_fetch.py
import requests
import json
from datetime import datetime, timedelta
HolySheep AI Konfiguration
HOLYSHEEP_API_URL = "https://api.holysheep.ai/v1"
HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY"
def fetch_tardis_kline_data(exchange: str, symbol: str, start_time: datetime, end_time: datetime):
"""
Ruft historische K-Line-Daten von Tardis via HolySheep AI ab
Parameter:
- exchange: 'binance', 'bybit', 'okx'
- symbol: z.B. 'BTC-USDT'
- start_time: Start der Datenreihe
- end_time: Ende der Datenreihe
"""
headers = {
"Authorization": f"Bearer {HOLYSHEEP_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"model": "deepseek-v3", # Kostengünstig für große Datenmengen
"messages": [
{
"role": "system",
"content": """Du bist ein Quant-Daten-Analyst. Generiere Python-Code
für Tardis-API-Abrufe mit automatischer Retry-Logik."""
},
{
"role": "user",
"content": f"""Erstelle Python-Code für:
1. Tardis K-Line Abruf von {exchange} {symbol}
2. Zeitraum: {start_time.isoformat()} bis {end_time.isoformat()}
3. Intervall: 1m, 5m, 1h
4. Mit GZIP-Dekomprimierung
5. Retry bei 429 Rate Limit (exponentiell)"""
}
],
"temperature": 0.1,
"max_tokens": 2000
}
response = requests.post(
f"{HOLYSHEEP_API_URL}/chat/completions",
headers=headers,
json=payload
)
if response.status_code == 200:
return response.json()["choices"][0]["message"]["content"]
elif response.status_code == 429:
# Rate Limit Handling
retry_after = int(response.headers.get("Retry-After", 60))
print(f"Rate limit erreicht. Warte {retry_after}s...")
import time
time.sleep(retry_after * 1.5) # 50% Puffer
return fetch_tardis_kline_data(exchange, symbol, start_time, end_time)
else:
raise Exception(f"API Fehler: {response.status_code}")
Beispielaufruf
kline_code = fetch_tardis_kline_data(
exchange="binance",
symbol="BTC-USDT",
start_time=datetime(2024, 1, 1),
end_time=datetime(2024, 12, 31)
)
print("Generierter Code:", kline_code)
Schritt 2: Datenvalidierung und Anomalieerkennung
# data_validation_pipeline.py
import pandas as pd
import numpy as np
from typing import List, Tuple, Optional
from dataclasses import dataclass
from datetime import datetime, timedelta
@dataclass
class ValidationResult:
"""Ergebnis der Datenvalidierung"""
is_valid: bool
gaps: List[Tuple[datetime, datetime]]
anomalies: pd.DataFrame
corrected_rows: int
removed_rows: int
class KLineDataValidator:
"""
Validiert und bereinigt K-Line-Daten für quantitatives Backtesting.
Erkennt und korrigiert gängige Datenprobleme.
"""
def __init__(self, max_gap_minutes: int = 30,
price_deviation_threshold: float = 0.05):
self.max_gap_minutes = max_gap_minutes
self.price_deviation_threshold = price_deviation_threshold
def validate(self, df: pd.DataFrame) -> ValidationResult:
"""
Hauptvalidierung: Lücken, Anomalien, Konsistenz
Args:
df: DataFrame mit Spalten [timestamp, open, high, low, close, volume]
"""
df = df.copy()
df['timestamp'] = pd.to_datetime(df['timestamp'])
df = df.sort_values('timestamp').reset_index(drop=True)
# 1. Lückenerkennung
gaps = self._detect_gaps(df)
# 2. Anomalieerkennung (statistisch)
anomalies = self._detect_price_anomalies(df)
# 3. OHLC-Konsistenzprüfung
df, corrected = self._fix_ohlc_consistency(df)
# 4. Volumenvalidierung
df, volume_removed = self._filter_volume_anomalies(df)
# 5. Zeitstempelbereinigung
df['timestamp'] = df['timestamp'].dt.floor('s')
return ValidationResult(
is_valid=len(anomalies) < len(df) * 0.01, # <1% Anomalien OK
gaps=gaps,
anomalies=anomalies,
corrected_rows=corrected,
removed_rows=volume_removed
)
def _detect_gaps(self, df: pd.DataFrame) -> List[Tuple[datetime, datetime]]:
"""Findet fehlende Zeitintervalle"""
gaps = []
df['time_diff'] = df['timestamp'].diff()
for idx in df[df['time_diff'] > timedelta(minutes=self.max_gap_minutes)].index:
prev_ts = df.loc[idx-1, 'timestamp']
curr_ts = df.loc[idx, 'timestamp']
gaps.append((prev_ts, curr_ts))
return gaps
def _detect_price_anomalies(self, df: pd.DataFrame) -> pd.DataFrame:
"""Erkennt Preisanomalien via Rolling Statistics"""
df['ma_20'] = df['close'].rolling(20, min_periods=10).mean()
df['std_20'] = df['close'].rolling(20, min_periods=10).std()
df['z_score'] = (df['close'] - df['ma_20']) / df['std_20']
anomalies = df[abs(df['z_score']) > 3].copy()
return anomalies[['timestamp', 'close', 'ma_20', 'z_score']]
def _fix_ohlc_consistency(self, df: pd.DataFrame) -> Tuple[pd.DataFrame, int]:
"""Korrigiert ungültige OHLC-Beziehungen"""
corrected = 0
# High muss >= Open, Close, Low sein
mask = df['high'] < df[['open', 'close', 'low']].max(axis=1)
df.loc[mask, 'high'] = df.loc[mask, ['open', 'close', 'low']].max(axis=1)
corrected += mask.sum()
# Low muss <= Open, Close, High sein
mask = df['low'] > df[['open', 'close', 'high']].min(axis=1)
df.loc[mask, 'low'] = df.loc[mask, ['open', 'close', 'high']].min(axis=1)
corrected += mask.sum()
return df, corrected
def _filter_volume_anomalies(self, df: pd.DataFrame) -> Tuple[pd.DataFrame, int]:
"""Filtert unplausible Volumendaten"""
df['volume_ma'] = df['volume'].rolling(50, min_periods=20).mean()
df['volume_std'] = df['volume'].rolling(50, min_periods=20).std()
# Volumen > 10 Std.-Abweichung = verdächtig
mask = (df['volume'] > df['volume_ma'] + 10 * df['volume_std'])
removed = mask.sum()
df = df[~mask].drop(columns=['volume_ma', 'volume_std', 'ma_20', 'std_20', 'z_score'])
return df, removed
Anwendung
validator = KLineDataValidator(max_gap_minutes=30, price_deviation_threshold=0.05)
Beispiel: Datenvalidierung
sample_data = pd.DataFrame({
'timestamp': pd.date_range('2024-01-01', periods=1000, freq='1min'),
'open': np.random.uniform(40000, 42000, 1000),
'high': np.random.uniform(41000, 43000, 1000),
'low': np.random.uniform(39000, 41000, 1000),
'close': np.random.uniform(40000, 42000, 1000),
'volume': np.random.uniform(10, 1000, 1000)
})
result = validator.validate(sample_data)
print(f"Validierung erfolgreich: {result.is_valid}")
print(f"Gefundene Lücken: {len(result.gaps)}")
print(f"Anomalien erkannt: {len(result.anomalies)}")
Schritt 3: Vollständige ETL-Pipeline mit HolySheep AI
# complete_etl_pipeline.py
import pandas as pd
import numpy as np
import requests
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import json
import hashlib
import sqlite3
class TardisETLPipeline:
"""
Komplette ETL-Pipeline für Tardis K-Line-Daten.
Verwendet HolySheep AI für intelligente Datenanreicherung.
"""
def __init__(self, api_key: str, db_path: str = "tardis_data.db"):
self.api_key = api_key
self.db_path = db_path
self.base_url = "https://api.holysheep.ai/v1"
self._init_database()
def _init_database(self):
"""Initialisiert SQLite-Datenbank für persistente Datenspeicherung"""
conn = sqlite3.connect(self.db_path)
conn.execute("""
CREATE TABLE IF NOT EXISTS klines (
id INTEGER PRIMARY KEY AUTOINCREMENT,
exchange TEXT NOT NULL,
symbol TEXT NOT NULL,
timestamp INTEGER NOT NULL,
open REAL, high REAL, low REAL, close REAL, volume REAL,
interval TEXT,
data_hash TEXT UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
conn.execute("""
CREATE INDEX IF NOT EXISTS idx_symbol_time
ON klines(exchange, symbol, timestamp)
""")
conn.commit()
conn.close()
def fetch_and_process(self, exchange: str, symbol: str,
start: datetime, end: datetime,
interval: str = "1m") -> Dict:
"""
Haupteinstiegspunkt: Holt, validiert und speichert Daten
Returns:
Dict mit Verarbeitungsstatistiken
"""
print(f"Starte ETL für {exchange}:{symbol}")
# 1. Daten von Tardis abrufen (via HolySheep optimiert)
raw_data = self._fetch_from_tardis(exchange, symbol, start, end, interval)
print(f" Rohdaten: {len(raw_data)} Einträge")
# 2. Datenvalidierung
validated_data = self._validate_data(raw_data)
print(f" Nach Validierung: {len(validated_data)} Einträge")
# 3. Anomaliebereinigung
cleaned_data = self._clean_anomalies(validated_data)
print(f" Nach Bereinigung: {len(cleaned_data)} Einträge")
# 4. Feature Engineering mit HolySheep AI
enriched_data = self._enrich_with_ai(cleaned_data)
# 5. Persistenz in Datenbank
saved_count = self._save_to_database(exchange, symbol, interval, enriched_data)
print(f" Gespeichert: {saved_count} Einträge")
return {
"raw": len(raw_data),
"validated": len(validated_data),
"cleaned": len(cleaned_data),
"enriched": len(enriched_data),
"saved": saved_count,
"hash": hashlib.md5(str(enriched_data).encode()).hexdigest()
}
def _fetch_from_tardis(self, exchange: str, symbol: str,
start: datetime, end: datetime,
interval: str) -> pd.DataFrame:
"""Ruft Daten von Tardis API ab mit Retry-Logik"""
# Tardis Streaming API Endpoint
tardis_url = f"https://tardis.dev/api/v1/compact-lite"
params = {
"exchange": exchange,
"symbol": symbol,
"from": int(start.timestamp()),
"to": int(end.timestamp()),
"format": "json",
"compress": "gzip"
}
# Retry-Logik mit exponentieller Backoff
max_retries = 3
for attempt in range(max_retries):
try:
response = requests.get(tardis_url, params=params, timeout=60)
if response.status_code == 200:
data = response.json()
return pd.DataFrame(data)
elif response.status_code == 429:
wait = 2 ** attempt * 10
print(f" Rate limit, warte {wait}s...")
import time; time.sleep(wait)
else:
raise Exception(f"Tardis Error: {response.status_code}")
except Exception as e:
if attempt == max_retries - 1:
raise
print(f" Fehler: {e}, Retry {attempt + 1}/{max_retries}")
return pd.DataFrame()
def _validate_data(self, df: pd.DataFrame) -> pd.DataFrame:
"""Basisvalidierung der Rohdaten"""
# Erforderliche Spalten prüfen
required = ['timestamp', 'open', 'high', 'low', 'close', 'volume']
missing = [col for col in required if col not in df.columns]
if missing:
raise ValueError(f"Fehlende Spalten: {missing}")
# Datentypen sicherstellen
for col in required:
df[col] = pd.to_numeric(df[col], errors='coerce')
# Nullwerte entfernen
df = df.dropna(subset=required)
# Duplikate entfernen (basierend auf Timestamp)
df = df.drop_duplicates(subset=['timestamp'], keep='last')
# Zeitlich sortieren
df = df.sort_values('timestamp').reset_index(drop=True)
return df
def _clean_anomalies(self, df: pd.DataFrame) -> pd.DataFrame:
"""Entfernt statistische Anomalien"""
original_len = len(df)
# 1. Preisanomalien (Z-Score > 5)
for col in ['open', 'high', 'low', 'close']:
ma = df[col].rolling(50, min_periods=20, center=True).mean()
std = df[col].rolling(50, min_periods=20, center=True).std()
z_score = abs((df[col] - ma) / std)
df = df[z_score < 5]
# 2. Volumenanomalien (> 20 Std. Abweichung)
vol_ma = df['volume'].rolling(50, min_periods=20).mean()
vol_std = df['volume'].rolling(50, min_periods=20).std()
df = df[(df['volume'] < vol_ma + 20 * vol_std)]
# 3. OHLC-Konsistenz
df = df[df['high'] >= df[['open', 'close', 'low']].max(axis=1)]
df = df[df['low'] <= df[['open', 'close', 'high']].min(axis=1)]
removed = original_len - len(df)
if removed > 0:
print(f" Entfernt: {removed} Anomalien ({removed/original_len*100:.1f}%)")
return df.reset_index(drop=True)
def _enrich_with_ai(self, df: pd.DataFrame) -> pd.DataFrame:
"""
Nutzt HolySheep AI für intelligente Feature-Anreicherung.
Ideal für komplexe Feature-Berechnung bei niedrigen Kosten.
"""
# Nur bei DeepSeek V3.2 wirklich kostengünstig
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
payload = {
"model": "deepseek-v3", # $0.42/MTok
"messages": [
{
"role": "system",
"content": "Du bist ein Quant-Feature-Engineering-Experte. Berechne technische Indikatoren."
},
{
"role": "user",
"content": f"""Analysiere diese {len(df)} K-Line-Daten und füge hinzu:
1. RSI (14)
2. MACD (12, 26, 9)
3. Bollinger Bands (20, 2)
4. ATR (14)
Antworte mit Python-Code als Pandas-Operationen.
Datenpreview:
{df[['timestamp', 'open', 'high', 'low', 'close', 'volume']].tail(5).to_dict()}"""
}
],
"temperature": 0.1,
"max_tokens": 1500
}
try:
response = requests.post(
f"{self.base_url}/chat/completions",
headers=headers,
json=payload,
timeout=30
)
if response.status_code == 200:
result = response.json()
# Hier würde normalerweise der generierte Code ausgeführt
# aus Platzgründen vereinfacht
df['ai_enriched'] = True
print(" KI-Anreicherung: Erfolgreich")
except Exception as e:
print(f" KI-Anreicherung fehlgeschlagen: {e}")
df['ai_enriched'] = False
return df
def _save_to_database(self, exchange: str, symbol: str,
interval: str, df: pd.DataFrame) -> int:
"""Speichert Daten in SQLite mit Deduplizierung"""
conn = sqlite3.connect(self.db_path)
# Data Hash für Deduplizierung
df['data_hash'] = df.apply(
lambda x: hashlib.md5(
f"{x['timestamp']}{x['open']}{x['close']}".encode()
).hexdigest(),
axis=1
)
# Nur neue Einträge einfügen
existing_hashes = pd.read_sql(
"SELECT data_hash FROM klines",
conn
)['data_hash'].tolist()
df_new = df[~df['data_hash'].isin(existing_hashes)]
if len(df_new) > 0:
df_new['exchange'] = exchange
df_new['symbol'] = symbol
df_new['interval'] = interval
df_new.to_sql('klines', conn, if_exists='append', index=False)
conn.close()
return len(df_new)
=== Hauptprogramm ===
if __name__ == "__main__":
# HolySheep AI API Key
API_KEY = "YOUR_HOLYSHEEP_API_KEY"
pipeline = TardisETLPipeline(
api_key=API_KEY,
db_path="quant_backtest.db"
)
# Beispiel: BTC-USDT 1-Minute K-Line für 2024
stats = pipeline.fetch_and_process(
exchange="binance",
symbol="BTC-USDT",
start=datetime(2024, 1, 1),
end=datetime(2024, 12, 31),
interval="1m"
)
print("\n=== Verarbeitungsstatistik ===")
print(f"Rohdaten: {stats['raw']:,}")
print(f"Validiert: {stats['validated']:,}")
print(f"Bereinigt: {stats['cleaned']:,}")
print(f"KI-angereichert: {stats['enriched']:,}")
print(f" Gespeichert: {stats['saved']:,}")
print(f" Daten-Hash: {stats['hash']}")
Häufige Fehler und Lösungen
Fehler 1: "Connection Timeout bei Tardis-Abruf"
Symptom: Timeout nach 30s beim Abruf großer Datenmengen.
# Lösung: Streaming-Download mit Chunked Encoding
import requests
import gzip
import io
def fetch_tardis_streaming(exchange: str, symbol: str,
start: int, end: int) -> pd.DataFrame:
"""
Stabile Datenabruf-Methode mit Streaming und Progress-Tracking
"""
url = f"https://tardis.dev/api/v1/compact-lite"
params = {
"exchange": exchange,
"symbol": symbol,
"from": start,
"to": end,
"compress": "gzip" # Reduziert Netzwerkzeit um ~70%
}
session = requests.Session()
session.headers.update({"Accept-Encoding": "gzip, deflate"})
# Timeout erhöhen + Retry-Logik
max_retries = 5
for attempt in range(max_retries):
try:
with session.get(url, params=params, stream=True,
timeout=(10, 300)) as response:
response.raise_for_status()
# GZIP dekomprimieren
content = gzip.decompress(response.content)
df = pd.read_json(io.BytesIO(content))
print(f"Erfolgreich: {len(df)} Einträge heruntergeladen")
return df
except requests.exceptions.Timeout:
wait = (attempt + 1) * 30
print(f"Timeout, warte {wait}s (Versuch {attempt+1}/{max_retries})")
import time; time.sleep(wait)
except requests.exceptions.ConnectionError:
# Exponential Backoff bei Connection Errors
import time
time.sleep(2 ** attempt * 5)
raise Exception("Max. Retries erreicht - bitte später erneut versuchen")
Fehler 2: "Survivorship Bias bei Backtesting"
Symptom: Strategie funktioniert in Backtest perfekt, aber live verliert.
# Lösung: Historische Asset-Liste inkludieren (inkl. delistierte)
def get_historical_universe(exchange: str, date: datetime) -> List[str]:
"""
Gibt ALLE Assets zurück, die am gegebenen Datum existierten.
Inklusive derer, die später delistiert wurden.
"""
# Tardis liefert keine delistierten Assets
# Wir nutzen CoinGecko für historische Listings
coingecko_url = "https://api.coingecko.com/api/v3/coins/"
# Historische Liste abrufen
params = {
"date": date.strftime("%d-%m-%Y"),
"per_page": 250,
"page": 1
}
response = requests.get(coingecko_url + "list", params=params)
all_coins = response.json()
# Mit Tardis-Symbolen matchen
trading_pairs = get_tardis_symbols(exchange)
# Nur Assets, die zum Zeitpunkt existierten
historical_assets = []
for coin in all_coins:
symbol = f"{coin['symbol'].upper()}-USDT"
if symbol in trading_pairs:
historical_assets.append({
'id': coin['id'],
'symbol': symbol,
'name': coin['name'],
'listed_at': coin.get('listing_date')
})
return historical_assets
Anpassung der Backtesting-Logik
def backtest_with_survivorship_bias_handling(strategy, historical_assets):
"""
Backtest, der nur Assets handelt, die zum jeweiligen Zeitpunkt existierten
"""
results = []
for date in trading_dates:
# Universum zum DATEDATUM abrufen
universe = get_historical_universe(exchange="binance", date=date)
# Nur diese Assets handeln
available_symbols = [a['symbol'] for a in universe]
signals = strategy.generate_signals(available_symbols, date)
for signal in signals:
# Verlierer (delistete Assets) explizit einbeziehen
results.append({
'date': date,
'symbol': signal['symbol'],
'pnl': calculate_realistic_pnl(signal, date),
'delisted': signal['symbol'] not in get_current_symbols()
})
return pd.DataFrame(results)
Fehler 3: "Falsche Zeitstempel-Konvertierung"
Symptom: K-Line-Daten starten 8 Stunden früher/später als erwartet (China-Timezone-Problem).
# Lösung: Explizite UTC-Konvertierung mit timezone-awareness
from datetime import timezone
import pytz
def normalize_timestamps(df: pd.DataFrame,
source_tz: str = "Asia/Shanghai",
target_tz: str = "UTC") -> pd.DataFrame:
"""
Normalisiert Timestamps von beliebiger Quelle nach UTC.
Tardis liefert standardmäßig in lokaler Exchange-Zeit:
- Binance: Asia/Shanghai (UTC+8)
- Bybit: Asia/Shanghai (UTC+8)
- OKX: Asia/Shanghai (UTC+8)
"""
df = df.copy()
# Quell-Zeitzone definieren