diff --git a/FinlyticNews/Migrations/20260813202646_CheckPendingNews.Designer.cs b/FinlyticNews/Migrations/20260813202646_CheckPendingNews.Designer.cs
new file mode 100644
index 0000000..914a348
--- /dev/null
+++ b/FinlyticNews/Migrations/20260813202646_CheckPendingNews.Designer.cs
@@ -0,0 +1,174 @@
+//
+using System;
+using FinlyticNews.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace FinlyticNews.Migrations
+{
+ [DbContext(typeof(NewsDbContext))]
+ [Migration("20260813202646_CheckPendingNews")]
+ partial class CheckPendingNews
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("FinlyticNews.Entities.ArticleSourceEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Source")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("ArticleSources");
+ });
+
+ modelBuilder.Entity("FinlyticNews.Entities.MatchedAssetEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Isin")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("NewsArticleId")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Isin");
+
+ b.HasIndex("NewsArticleId");
+
+ b.ToTable("MatchedAssets");
+ });
+
+ modelBuilder.Entity("FinlyticNews.Entities.NewsArticleEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Author")
+ .HasColumnType("text");
+
+ b.Property("ContentRaw")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Language")
+ .HasColumnType("text");
+
+ b.Property("PublishedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("ScrapedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("SourceUrl")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Summary")
+ .HasColumnType("text");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SourceUrl")
+ .IsUnique();
+
+ b.HasIndex("Status");
+
+ b.HasIndex("PublishedAt", "ScrapedAt");
+
+ b.ToTable("NewsArticles");
+ });
+
+ modelBuilder.Entity("FinlyticNews.Entities.NewsSettingsEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("ArticleRetentionDays")
+ .HasColumnType("integer");
+
+ b.Property("DefaultPageSize")
+ .HasColumnType("integer");
+
+ b.Property("N8nWebhookUrl")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("PollingFrequencyMinutes")
+ .HasColumnType("integer");
+
+ b.Property("ScrapingIntervalMinutes")
+ .HasColumnType("integer");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.HasKey("Id");
+
+ b.ToTable("Settings");
+ });
+
+ modelBuilder.Entity("FinlyticNews.Entities.MatchedAssetEntity", b =>
+ {
+ b.HasOne("FinlyticNews.Entities.NewsArticleEntity", "NewsArticle")
+ .WithMany("MatchedAssets")
+ .HasForeignKey("NewsArticleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("NewsArticle");
+ });
+
+ modelBuilder.Entity("FinlyticNews.Entities.NewsArticleEntity", b =>
+ {
+ b.Navigation("MatchedAssets");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/FinlyticNews/Migrations/20260813202646_CheckPendingNews.cs b/FinlyticNews/Migrations/20260813202646_CheckPendingNews.cs
new file mode 100644
index 0000000..407245a
--- /dev/null
+++ b/FinlyticNews/Migrations/20260813202646_CheckPendingNews.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace FinlyticNews.Migrations
+{
+ ///
+ public partial class CheckPendingNews : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+
+ }
+ }
+}
diff --git a/FinlyticSentiment/Migrations/20260813202634_CheckPendingSentiment.Designer.cs b/FinlyticSentiment/Migrations/20260813202634_CheckPendingSentiment.Designer.cs
new file mode 100644
index 0000000..a43b810
--- /dev/null
+++ b/FinlyticSentiment/Migrations/20260813202634_CheckPendingSentiment.Designer.cs
@@ -0,0 +1,63 @@
+//
+using System;
+using FinlyticSentiment.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace FinlyticSentiment.Migrations
+{
+ [DbContext(typeof(SentimentDbContext))]
+ [Migration("20260813202634_CheckPendingSentiment")]
+ partial class CheckPendingSentiment
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("FinlyticSentiment.Entities.SentimentSettingsEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("EnglishWebhookUrl")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)");
+
+ b.Property("GermanWebhookUrl")
+ .IsRequired()
+ .HasMaxLength(500)
+ .HasColumnType("character varying(500)");
+
+ b.Property("MaxBatchSize")
+ .HasColumnType("integer");
+
+ b.Property("MinConfidenceScore")
+ .HasColumnType("double precision");
+
+ b.Property("SweepIntervalMinutes")
+ .HasColumnType("integer");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.HasKey("Id");
+
+ b.ToTable("sentiment_settings", (string)null);
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/FinlyticSentiment/Migrations/20260813202634_CheckPendingSentiment.cs b/FinlyticSentiment/Migrations/20260813202634_CheckPendingSentiment.cs
new file mode 100644
index 0000000..3271db9
--- /dev/null
+++ b/FinlyticSentiment/Migrations/20260813202634_CheckPendingSentiment.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace FinlyticSentiment.Migrations
+{
+ ///
+ public partial class CheckPendingSentiment : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+
+ }
+ }
+}
diff --git a/FinlyticTechnicalAnalysis/Database/TechnicalAnalysisDbContext.cs b/FinlyticTechnicalAnalysis/Database/TechnicalAnalysisDbContext.cs
index 1c6f7de..056a344 100644
--- a/FinlyticTechnicalAnalysis/Database/TechnicalAnalysisDbContext.cs
+++ b/FinlyticTechnicalAnalysis/Database/TechnicalAnalysisDbContext.cs
@@ -1,3 +1,4 @@
+using FinlyticCore.Entities.Settings;
using FinlyticTechnicalAnalysis.Entities;
using Microsoft.EntityFrameworkCore;
@@ -9,6 +10,7 @@ public class TechnicalAnalysisDbContext : DbContext
{
}
+ public DbSet DynamicSettings => Set();
public DbSet MarketCandles => Set();
public DbSet MacroData => Set();
public DbSet CachedAnalyses => Set();
@@ -18,6 +20,12 @@ public class TechnicalAnalysisDbContext : DbContext
{
base.OnModelCreating(modelBuilder);
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id);
+ entity.HasIndex(e => e.Key);
+ });
+
modelBuilder.Entity()
.HasIndex(c => new { c.Symbol, c.Interval, c.Timestamp })
.IsUnique();
diff --git a/FinlyticTechnicalAnalysis/Migrations/20260813202624_CheckPendingTechnicalAnalysis.Designer.cs b/FinlyticTechnicalAnalysis/Migrations/20260813202624_CheckPendingTechnicalAnalysis.Designer.cs
new file mode 100644
index 0000000..0c6fc46
--- /dev/null
+++ b/FinlyticTechnicalAnalysis/Migrations/20260813202624_CheckPendingTechnicalAnalysis.Designer.cs
@@ -0,0 +1,162 @@
+//
+using System;
+using FinlyticTechnicalAnalysis.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace FinlyticTechnicalAnalysis.Migrations
+{
+ [DbContext(typeof(TechnicalAnalysisDbContext))]
+ [Migration("20260813202624_CheckPendingTechnicalAnalysis")]
+ partial class CheckPendingTechnicalAnalysis
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.9")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("FinlyticTechnicalAnalysis.Entities.CachedAnalysisEntity", b =>
+ {
+ b.Property("Isin")
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)");
+
+ b.Property("AnalysisJson")
+ .IsRequired()
+ .HasColumnType("jsonb");
+
+ b.Property("CalculatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Ticker")
+ .IsRequired()
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)");
+
+ b.HasKey("Isin");
+
+ b.HasIndex("Isin");
+
+ b.ToTable("CachedAnalyses");
+ });
+
+ modelBuilder.Entity("FinlyticTechnicalAnalysis.Entities.MacroDataEntity", b =>
+ {
+ b.Property("Symbol")
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)");
+
+ b.Property("LastUpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("PreviousClose")
+ .HasColumnType("decimal(18, 6)");
+
+ b.Property("TrendState")
+ .IsRequired()
+ .HasMaxLength(50)
+ .HasColumnType("character varying(50)");
+
+ b.Property("Value")
+ .HasColumnType("decimal(18, 6)");
+
+ b.HasKey("Symbol");
+
+ b.ToTable("MacroData");
+ });
+
+ modelBuilder.Entity("FinlyticTechnicalAnalysis.Entities.MarketCandleEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Ask")
+ .HasColumnType("decimal(18, 6)");
+
+ b.Property("Bid")
+ .HasColumnType("decimal(18, 6)");
+
+ b.Property("Close")
+ .HasColumnType("decimal(18, 6)");
+
+ b.Property("High")
+ .HasColumnType("decimal(18, 6)");
+
+ b.Property("Interval")
+ .IsRequired()
+ .HasMaxLength(10)
+ .HasColumnType("character varying(10)");
+
+ b.Property("Low")
+ .HasColumnType("decimal(18, 6)");
+
+ b.Property("Open")
+ .HasColumnType("decimal(18, 6)");
+
+ b.Property("Symbol")
+ .IsRequired()
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)");
+
+ b.Property("Timestamp")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Volume")
+ .HasColumnType("bigint");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Symbol", "Interval", "Timestamp")
+ .IsUnique();
+
+ b.ToTable("MarketCandles");
+ });
+
+ modelBuilder.Entity("FinlyticTechnicalAnalysis.Entities.TaSettingsEntity", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("EmaShortPeriod")
+ .HasColumnType("integer");
+
+ b.Property("RsiOverboughtLimit")
+ .HasColumnType("double precision");
+
+ b.Property("RsiOversoldLimit")
+ .HasColumnType("double precision");
+
+ b.Property("SmaLongPeriod")
+ .HasColumnType("integer");
+
+ b.Property("SmaMediumPeriod")
+ .HasColumnType("integer");
+
+ b.Property("SupertrendMultiplier")
+ .HasColumnType("double precision");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.HasKey("Id");
+
+ b.ToTable("Settings");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/FinlyticTechnicalAnalysis/Migrations/20260813202624_CheckPendingTechnicalAnalysis.cs b/FinlyticTechnicalAnalysis/Migrations/20260813202624_CheckPendingTechnicalAnalysis.cs
new file mode 100644
index 0000000..a540ee0
--- /dev/null
+++ b/FinlyticTechnicalAnalysis/Migrations/20260813202624_CheckPendingTechnicalAnalysis.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace FinlyticTechnicalAnalysis.Migrations
+{
+ ///
+ public partial class CheckPendingTechnicalAnalysis : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+
+ }
+ }
+}
diff --git a/FinlyticTechnicalAnalysis/Program.cs b/FinlyticTechnicalAnalysis/Program.cs
index 913f883..76bdf77 100644
--- a/FinlyticTechnicalAnalysis/Program.cs
+++ b/FinlyticTechnicalAnalysis/Program.cs
@@ -30,10 +30,10 @@ builder.Services.AddSingleton();
// Register Technical Analysis Services
builder.Services.AddSingleton();
-builder.Services.AddSingleton();
+builder.Services.AddTransient();
builder.Services.AddScoped();
-builder.Services.AddScoped();
-builder.Services.AddScoped();
+builder.Services.AddTransient();
+builder.Services.AddSingleton();
// Register MQTT Client (as a Hosted Service)
builder.Services.AddHostedService();