using IBKRTrader.Core.Logging; namespace IBKRTrader.Core.Database.Migrations; /// /// Erstellt die core_ibkr_xxx-Tabellen idempotent (IF NOT EXISTS). /// Wird beim App-Start nach CoreMigrations ausgeführt. /// public class IBKRMigrations { private readonly DatabaseService _db; private readonly LoggingService _logger; public IBKRMigrations(DatabaseService db, LoggingService logger) { _db = db; _logger = logger; } public async Task RunAsync() { _logger.Info("Core", "Starte IBKR-Datenbankmigrationen..."); await CreateInstrumentsTableAsync(); await CreateMarketDataTableAsync(); await CreateExternalIdentifiersTableAsync(); _logger.Info("Core", "IBKR-Migrationen abgeschlossen."); } // ─── Tabellen ───────────────────────────────────────────────────────────── private Task CreateInstrumentsTableAsync() => _db.ExecuteAsync(@" CREATE TABLE IF NOT EXISTS `core_ibkr_instruments` ( `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, `ibkr_conid` BIGINT NOT NULL UNIQUE, `symbol` VARCHAR(20) NOT NULL, `sec_type` VARCHAR(10) NOT NULL DEFAULT 'STK', `exchange` VARCHAR(20) NOT NULL DEFAULT 'SMART', `primary_exchange` VARCHAR(20), `currency` VARCHAR(5) NOT NULL DEFAULT 'USD', `company_name` TEXT, `isin` VARCHAR(12), `sector` VARCHAR(100), `industry` VARCHAR(100), `description` TEXT, `active` TINYINT(1) NOT NULL DEFAULT 1, `last_fetched` DATETIME, `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX `idx_symbol` (`symbol`), INDEX `idx_conid` (`ibkr_conid`), INDEX `idx_active` (`active`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); private Task CreateMarketDataTableAsync() => _db.ExecuteAsync(@" CREATE TABLE IF NOT EXISTS `core_ibkr_market_data` ( `instrument_id` BIGINT NOT NULL, `bar_size` VARCHAR(10) NOT NULL DEFAULT 'daily', `timestamp` DATETIME NOT NULL, `open` DECIMAL(12,6), `high` DECIMAL(12,6), `low` DECIMAL(12,6), `close` DECIMAL(12,6), `volume` BIGINT, `wap` DECIMAL(12,6), `bar_count` INT, PRIMARY KEY (`instrument_id`, `bar_size`, `timestamp`), INDEX `idx_timestamp` (`timestamp`), CONSTRAINT `fk_md_instrument` FOREIGN KEY (`instrument_id`) REFERENCES `core_ibkr_instruments` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); private Task CreateExternalIdentifiersTableAsync() => _db.ExecuteAsync(@" CREATE TABLE IF NOT EXISTS `core_ibkr_external_identifiers` ( `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, `instrument_id` BIGINT NOT NULL, `source` VARCHAR(50) NOT NULL, `ticker` VARCHAR(50) NOT NULL, `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `uq_mapping` (`instrument_id`, `source`, `ticker`), INDEX `idx_source_ticker` (`source`, `ticker`), CONSTRAINT `fk_ext_instrument` FOREIGN KEY (`instrument_id`) REFERENCES `core_ibkr_instruments` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); }