.NET WinForms-Anwendung (Core, Modules/CongressTrading, UI). Enthaelt .gitignore und settings.example.json als Konfigurationsvorlage. Echte settings.json mit Zugangsdaten ist bewusst ausgeschlossen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
129 lines
7.3 KiB
Plaintext
129 lines
7.3 KiB
Plaintext
Deine Datenbankstruktur sollte genau auf die IBKR-Web-API abgestimmt sein – vor allem auf den zentralen conid (Contract ID).
|
||
Ich habe mir die komplette Web-API-Dokumentation zum Tag „Trading-Contracts“ (und die damit verknüpften Endpoints /iserver/secdef/search, /trsrv/stocks, /trsrv/secdef etc.) angeschaut. Die wichtigsten Erkenntnisse daraus:
|
||
|
||
Symbol allein reicht nie (AAPL gibt es z. B. auf NASDAQ, MEXI, LSE etc.).
|
||
Der conid ist der einzige stabile, eindeutige Schlüssel in IBKR (z. B. AAPL US Stock = conid: 265598). Er ändert sich nie und wird für alle Market-Data-, Order- und Positions-Calls verwendet.
|
||
IBKR liefert über die Search-Endpoints automatisch companyName, sector, primaryExchange, validExchanges etc. mit – das kannst du direkt in die DB schreiben.
|
||
Historische Daten (und alle Trades) referenzieren immer nur den conid.
|
||
|
||
Genau das nutzen wir für die Datenbank. Ich schlage eine saubere, skalierbare und zukunftssichere Struktur vor (PostgreSQL + TimescaleDB für die Zeitreihen ist ideal, funktioniert aber auch mit normalem Postgres).
|
||
1. Kern-Tabellen (relational)
|
||
SQL-- 1. Instruments = IBKR-Contract (der zentrale „Single Source of Truth“)
|
||
CREATE TABLE instruments (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
ibkr_conid BIGINT NOT NULL UNIQUE, -- wichtigster Key!
|
||
symbol VARCHAR(20) NOT NULL,
|
||
sec_type VARCHAR(10) NOT NULL, -- STK, OPT, FUT, BOND ...
|
||
exchange VARCHAR(20) NOT NULL, -- NASDAQ, SMART, NYSE ...
|
||
primary_exchange VARCHAR(20),
|
||
currency VARCHAR(3) NOT NULL,
|
||
company_name TEXT,
|
||
local_symbol VARCHAR(20),
|
||
trading_class VARCHAR(20),
|
||
isin VARCHAR(12), -- oft nützlich
|
||
sector VARCHAR(100),
|
||
industry VARCHAR(100),
|
||
description TEXT,
|
||
has_options BOOLEAN,
|
||
asset_class VARCHAR(10),
|
||
listing_exchange VARCHAR(20),
|
||
last_fetched TIMESTAMPTZ DEFAULT NOW(),
|
||
active BOOLEAN DEFAULT true,
|
||
custom_metadata JSONB, -- flexibler Platz für alles, was du später brauchst
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 2. External Identifiers = Verknüpfung zu allen anderen Quellen
|
||
CREATE TABLE external_identifiers (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
instrument_id BIGINT REFERENCES instruments(id) ON DELETE CASCADE,
|
||
source VARCHAR(50) NOT NULL, -- 'yahoo', 'alpha_vantage', 'bloomberg', 'web_scrape', 'manual', 'tradingview' ...
|
||
ticker VARCHAR(50) NOT NULL,
|
||
additional_params JSONB, -- z. B. {'exchange': 'NYSE', 'region': 'US'}
|
||
priority SMALLINT DEFAULT 1, -- falls mehrere Ticker für dieselbe Quelle existieren
|
||
last_verified TIMESTAMPTZ,
|
||
UNIQUE (instrument_id, source, ticker)
|
||
);
|
||
|
||
-- Index für schnelle Lookups
|
||
CREATE INDEX idx_external_source_ticker ON external_identifiers(source, ticker);
|
||
CREATE INDEX idx_instrument_conid ON instruments(ibkr_conid);
|
||
Warum diese Trennung?
|
||
Du bekommst z. B. von einer Web-Analyse oder einem Scraping-Tool den Ticker „AAPL“. Du schaust in external_identifiers nach → findest sofort das instrument_id → hast den ibkr_conid und alle IBKR-spezifischen Daten.
|
||
2. Eigene Informationen & Analysen (sehr flexibel)
|
||
Du kannst zwei Wege gehen – ich empfehle beide gleichzeitig:
|
||
Variante A (einfach & schnell): Die Spalte custom_metadata JSONB in der instruments-Tabelle (siehe oben). Dort kannst du beliebig strukturierte eigene Daten speichern:
|
||
JSON{
|
||
"ai_sentiment_score": 0.87,
|
||
"my_strategy_rating": "strong_buy",
|
||
"notes": "Apple AI-Investitionen 2025 sehr interessant",
|
||
"last_ai_analysis": "2026-05-10",
|
||
"custom_pe_target": 32.5,
|
||
"watchlist_tags": ["growth", "tech", "ai"]
|
||
}
|
||
Variante B (noch flexibler, für sehr viele eigene Felder): Eine separate EAV-Tabelle:
|
||
SQLCREATE TABLE instrument_custom_data (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
instrument_id BIGINT REFERENCES instruments(id) ON DELETE CASCADE,
|
||
key VARCHAR(100) NOT NULL, -- z. B. 'ai_sentiment', 'my_risk_score'
|
||
value JSONB,
|
||
source VARCHAR(20), -- 'user', 'gpt-4o', 'claude' ...
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
UNIQUE (instrument_id, key)
|
||
);
|
||
3. Historische Marktdaten (Time-Series)
|
||
SQL-- Mit TimescaleDB (empfohlen) oder normaler Postgres-Tabelle
|
||
CREATE TABLE market_data (
|
||
instrument_id BIGINT REFERENCES instruments(id) ON DELETE CASCADE,
|
||
data_source VARCHAR(20) DEFAULT 'ibkr', -- 'ibkr', 'yahoo', 'polygon' ...
|
||
bar_size VARCHAR(10) NOT NULL, -- '1min', '5min', '15min', '1hour', 'daily', 'weekly' ...
|
||
timestamp TIMESTAMPTZ NOT NULL,
|
||
open NUMERIC(12,6),
|
||
high NUMERIC(12,6),
|
||
low NUMERIC(12,6),
|
||
close NUMERIC(12,6),
|
||
volume BIGINT,
|
||
wap NUMERIC(12,6), -- weighted average price (IBKR)
|
||
count INTEGER, -- Anzahl Trades in der Bar
|
||
additional_data JSONB, -- falls andere Quellen mehr Felder liefern
|
||
PRIMARY KEY (instrument_id, data_source, bar_size, timestamp)
|
||
);
|
||
|
||
-- Timescale-Hypertable (sehr performant bei Millionen von Zeilen)
|
||
SELECT create_hypertable('market_data', 'timestamp', chunk_time_interval => INTERVAL '7 days');
|
||
Zukunftssicherheit:
|
||
Durch data_source kannst du später problemlos Polygon, Yahoo, Alpha Vantage etc. hinzufügen, ohne die Struktur zu ändern.
|
||
4. Zusätzliche nützliche Tabellen (optional, aber sehr empfehlenswert)
|
||
|
||
data_imports → Log-Tabelle (wann welcher Ticker von welcher Quelle importiert wurde, Status, Fehler)
|
||
fundamental_data → Bilanz-/Gewinn- und Verlustdaten (kann auch als JSONB in instruments oder eigene Tabelle)
|
||
orders / trades → Deine automatisch platzierten IBKR-Orders (mit ibkr_conid, Order-ID, Status etc.)
|
||
watchlists / portfolios → Deine eigenen Watchlists mit eigenen Tags
|
||
|
||
Praktische Umsetzungstipps
|
||
|
||
Mapping-Prozess (wichtigster Teil deines Tools):
|
||
Neue externe Ticker kommen herein → erst /iserver/secdef/search?symbol=... oder /trsrv/stocks?symbols=... aufrufen.
|
||
Ergebnis in instruments speichern (falls neu) + Mapping in external_identifiers.
|
||
Danach immer nur noch über ibkr_conid arbeiten.
|
||
|
||
Performance & Skalierung:
|
||
ibkr_conid + symbol + exchange stark indizieren.
|
||
Für sehr viele Instrumente (>> 10.000) lohnt sich eine separate instrument_aliases oder Cache-Layer (Redis).
|
||
|
||
Flexibilität für weitere Datenquellen:
|
||
Immer data_source und external_identifiers benutzen → du bist komplett unabhängig von IBKR als einziger Datenquelle.
|
||
|
||
Eigene Infos für Apple & Co.:
|
||
Einfach in custom_metadata oder instrument_custom_data schreiben. Die AI kann dort direkt Ergebnisse ablegen.
|
||
|
||
|
||
Diese Struktur ist praxisbewährt (ähnliche Schemata laufen bei vielen algo-Tradern mit IBKR + externen Daten). Sie ist gleichzeitig schlank und extrem erweiterbar.
|
||
Wenn du möchtest, kann ich dir:
|
||
|
||
das komplette SQL-Skript (mit allen Indizes, Triggers, Timescale-Setup),
|
||
ein Python-Beispiel mit SQLAlchemy + IBKR-WebAPI-Client zum automatischen Mapping,
|
||
oder ein ER-Diagramm (Mermaid) liefern.
|
||
|
||
Sag einfach Bescheid, wo du als Nächstes tiefer einsteigen willst! |