Initial commit: IBKRTrader
.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>
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
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!
|
||||
Reference in New Issue
Block a user