using System; using System.Net.Http; using FinlyticCore.Database; using FinlyticCore.Services; using FinlyticCore.Services.TradeRepublic; using FinlyticCore.Services.Yahoo; using FinlyticTechnicals.Database; using FinlyticTechnicals.Patterns; using FinlyticTechnicals.Patterns.Candlesticks; using FinlyticTechnicals.Patterns.ChartPatterns; using FinlyticTechnicals.Patterns.SmartMoney; using FinlyticTechnicals.Services; using FinlyticTechnicals.Strategies; using FinlyticTechnicals.Util; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; var builder = Host.CreateApplicationBuilder(args); // 1. Register DbContext builder.Services.AddDbContext(options => options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); builder.Services.AddScoped(sp => sp.GetRequiredService()); // 2. Register Core Services & Logger builder.Services.AddSingleton(); builder.Services.AddSingleton(typeof(IFinlyticLogger<>), typeof(FinlyticLogger<>)); // 3. Register HTTP & Market Data Clients builder.Services.AddHttpClient() .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { UseCookies = true, CookieContainer = new System.Net.CookieContainer() }); builder.Services.AddSingleton(); builder.Services.AddTransient(); // 4. Register Trade Republic Ingestion & Real-Time Services builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); // 5. Register Pattern Detectors builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); // 6. Register Strategies builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); // 7. Register Technical Scoring Engine & Universe Manager // builder.Services.AddSingleton(); // V1 Fallback builder.Services.AddSingleton(); // V2 Bidirectional Active builder.Services.AddSingleton(); // 8. Register MQTT Client & RPC Bridge builder.Services.AddSingleton(); builder.Services.AddSingleton(sp => sp.GetRequiredService()); builder.Services.AddHostedService(sp => sp.GetRequiredService()); // 9. Register Technical Scanner Background Service builder.Services.AddHostedService(); var host = builder.Build(); // Run startup database migrations using (var scope = host.Services.CreateScope()) { try { var context = scope.ServiceProvider.GetRequiredService(); var connStr = builder.Configuration.GetConnectionString("DefaultConnection") ?? ""; await context.MigrateWithBootstrapAsync(connStr); Console.WriteLine("Database migrations successfully executed for FinlyticTechnicals."); // The monitored-universe table backs TechnicalUniverseManager but is deliberately NOT meant to survive // a restart: it is fully rebuilt within minutes from RefreshFavoritesAsync/RefreshDiscoveryAsync and // fresh sentiment-spike events, and a stale row whose TTL never got swept because the process was down // is worse than starting from an empty universe. await context.MonitoredUniverseAssets.ExecuteDeleteAsync(); Console.WriteLine("Monitored universe table cleared for fresh start."); } catch (Exception ex) { Console.WriteLine($"Migration error on startup: {ex.Message}"); } } await host.RunAsync();