feat(analyzer): update MQTT handler, active trade monitoring, and dynamic settings

This commit is contained in:
2026-08-14 23:55:52 +02:00
parent 4d5ab09bbd
commit c496651dd1
8 changed files with 778 additions and 45 deletions
@@ -0,0 +1,277 @@
// <auto-generated />
using System;
using FinlyticAnalyzer.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 FinlyticAnalyzer.Migrations
{
[DbContext(typeof(AnalyzerDbContext))]
[Migration("20260813202556_CheckPendingAnalyzer")]
partial class CheckPendingAnalyzer
{
/// <inheritdoc />
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("FinlyticAnalyzer.Entities.AnalysisEntity", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("AiOutputJson")
.IsRequired()
.HasColumnType("jsonb");
b.Property<string>("AnalysisId")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("EventId")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<double>("ImpactScore")
.HasColumnType("double precision");
b.Property<bool>("IsTradeProposed")
.HasColumnType("boolean");
b.Property<string>("Isin")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<string>("N8nDecision")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<double>("N8nEvalScore")
.HasColumnType("double precision");
b.Property<string>("N8nResponseJson")
.IsRequired()
.HasColumnType("jsonb");
b.Property<string>("RawDataJson")
.IsRequired()
.HasColumnType("jsonb");
b.Property<string>("Sector")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("Symbol")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<int>("VixRegime")
.HasColumnType("integer");
b.Property<decimal>("VixValue")
.HasColumnType("numeric");
b.Property<double>("WinRate")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("AnalysisId")
.IsUnique();
b.HasIndex("CreatedAt");
b.HasIndex("EventId");
b.HasIndex("Isin");
b.HasIndex("Sector");
b.ToTable("analyses");
});
modelBuilder.Entity("FinlyticAnalyzer.Entities.AnalyzerSettingsEntity", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("EnableLogAnalyzerAuto")
.HasColumnType("boolean");
b.Property<bool>("EnableLogAnalyzerManual")
.HasColumnType("boolean");
b.Property<bool>("EnableLogDatabaseOps")
.HasColumnType("boolean");
b.Property<bool>("EnableLogMqttGeneral")
.HasColumnType("boolean");
b.Property<bool>("EnableLogMqttHealthPing")
.HasColumnType("boolean");
b.Property<double>("MinSignalScore")
.HasColumnType("double precision");
b.Property<string>("ScanCronSchedule")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("Settings");
});
modelBuilder.Entity("FinlyticAnalyzer.Entities.TradeProposalEntity", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("AnalysisId")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<double>("ConfidenceScore")
.HasColumnType("double precision");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<decimal>("EntryPrice")
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("EntryZoneMax")
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("EntryZoneMin")
.HasColumnType("decimal(18,4)");
b.Property<string>("EventId")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("FundamentalRationale")
.IsRequired()
.HasColumnType("text");
b.Property<string>("InstrumentType")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<string>("Isin")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<decimal?>("MaxLeverage")
.HasColumnType("decimal(18,4)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<string>("ProposedAction")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<string>("ReasonSummary")
.IsRequired()
.HasColumnType("text");
b.Property<decimal?>("RiskRewardRatio")
.HasColumnType("decimal(18,4)");
b.Property<string>("RiskTolerance")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<string>("RiskWarning")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Sector")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<decimal>("StopLoss")
.HasColumnType("decimal(18,4)");
b.Property<string>("Symbol")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<decimal>("TakeProfit")
.HasColumnType("decimal(18,4)");
b.Property<string>("TakeProfitTargets")
.HasColumnType("text");
b.Property<string>("TechnicalRationale")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Timeframe")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<int>("VixRegime")
.HasColumnType("integer");
b.Property<decimal>("VixValue")
.HasColumnType("decimal(18,4)");
b.Property<double>("WinRate")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("ExpiresAt");
b.HasIndex("Isin");
b.ToTable("trade_proposals");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,351 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FinlyticAnalyzer.Migrations
{
/// <inheritdoc />
public partial class CheckPendingAnalyzer : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_TradeProposals",
table: "TradeProposals");
migrationBuilder.RenameTable(
name: "TradeProposals",
newName: "trade_proposals");
migrationBuilder.RenameIndex(
name: "IX_TradeProposals_Isin",
table: "trade_proposals",
newName: "IX_trade_proposals_Isin");
migrationBuilder.RenameIndex(
name: "IX_TradeProposals_ExpiresAt",
table: "trade_proposals",
newName: "IX_trade_proposals_ExpiresAt");
migrationBuilder.AlterColumn<string>(
name: "ProposedAction",
table: "trade_proposals",
type: "character varying(20)",
maxLength: 20,
nullable: false,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "trade_proposals",
type: "character varying(150)",
maxLength: 150,
nullable: false,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AlterColumn<string>(
name: "Isin",
table: "trade_proposals",
type: "character varying(30)",
maxLength: 30,
nullable: false,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddColumn<string>(
name: "AnalysisId",
table: "trade_proposals",
type: "character varying(100)",
maxLength: 100,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<decimal>(
name: "EntryPrice",
table: "trade_proposals",
type: "numeric(18,4)",
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<decimal>(
name: "EntryZoneMax",
table: "trade_proposals",
type: "numeric(18,4)",
nullable: true);
migrationBuilder.AddColumn<decimal>(
name: "EntryZoneMin",
table: "trade_proposals",
type: "numeric(18,4)",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "EventId",
table: "trade_proposals",
type: "character varying(100)",
maxLength: 100,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "FundamentalRationale",
table: "trade_proposals",
type: "text",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "InstrumentType",
table: "trade_proposals",
type: "character varying(30)",
maxLength: 30,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<decimal>(
name: "MaxLeverage",
table: "trade_proposals",
type: "numeric(18,4)",
nullable: true);
migrationBuilder.AddColumn<decimal>(
name: "RiskRewardRatio",
table: "trade_proposals",
type: "numeric(18,4)",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "RiskTolerance",
table: "trade_proposals",
type: "character varying(30)",
maxLength: 30,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "RiskWarning",
table: "trade_proposals",
type: "text",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Sector",
table: "trade_proposals",
type: "character varying(50)",
maxLength: 50,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<decimal>(
name: "StopLoss",
table: "trade_proposals",
type: "numeric(18,4)",
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<string>(
name: "Symbol",
table: "trade_proposals",
type: "character varying(30)",
maxLength: 30,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<decimal>(
name: "TakeProfit",
table: "trade_proposals",
type: "numeric(18,4)",
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<string>(
name: "TakeProfitTargets",
table: "trade_proposals",
type: "text",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "TechnicalRationale",
table: "trade_proposals",
type: "text",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Timeframe",
table: "trade_proposals",
type: "character varying(20)",
maxLength: 20,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<int>(
name: "VixRegime",
table: "trade_proposals",
type: "integer",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<decimal>(
name: "VixValue",
table: "trade_proposals",
type: "numeric(18,4)",
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<double>(
name: "WinRate",
table: "trade_proposals",
type: "double precision",
nullable: false,
defaultValue: 0.0);
migrationBuilder.AddPrimaryKey(
name: "PK_trade_proposals",
table: "trade_proposals",
column: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_trade_proposals",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "AnalysisId",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "EntryPrice",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "EntryZoneMax",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "EntryZoneMin",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "EventId",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "FundamentalRationale",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "InstrumentType",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "MaxLeverage",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "RiskRewardRatio",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "RiskTolerance",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "RiskWarning",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "Sector",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "StopLoss",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "Symbol",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "TakeProfit",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "TakeProfitTargets",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "TechnicalRationale",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "Timeframe",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "VixRegime",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "VixValue",
table: "trade_proposals");
migrationBuilder.DropColumn(
name: "WinRate",
table: "trade_proposals");
migrationBuilder.RenameTable(
name: "trade_proposals",
newName: "TradeProposals");
migrationBuilder.RenameIndex(
name: "IX_trade_proposals_Isin",
table: "TradeProposals",
newName: "IX_TradeProposals_Isin");
migrationBuilder.RenameIndex(
name: "IX_trade_proposals_ExpiresAt",
table: "TradeProposals",
newName: "IX_TradeProposals_ExpiresAt");
migrationBuilder.AlterColumn<string>(
name: "ProposedAction",
table: "TradeProposals",
type: "text",
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(20)",
oldMaxLength: 20);
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "TradeProposals",
type: "text",
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(150)",
oldMaxLength: 150);
migrationBuilder.AlterColumn<string>(
name: "Isin",
table: "TradeProposals",
type: "text",
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(30)",
oldMaxLength: 30);
migrationBuilder.AddPrimaryKey(
name: "PK_TradeProposals",
table: "TradeProposals",
column: "Id");
}
}
}
@@ -149,41 +149,124 @@ namespace FinlyticAnalyzer.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("AnalysisId")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<double>("ConfidenceScore")
.HasColumnType("double precision");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<decimal>("EntryPrice")
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("EntryZoneMax")
.HasColumnType("decimal(18,4)");
b.Property<decimal?>("EntryZoneMin")
.HasColumnType("decimal(18,4)");
b.Property<string>("EventId")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Isin")
b.Property<string>("FundamentalRationale")
.IsRequired()
.HasColumnType("text");
b.Property<string>("InstrumentType")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<string>("Isin")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<decimal?>("MaxLeverage")
.HasColumnType("decimal(18,4)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
.HasMaxLength(150)
.HasColumnType("character varying(150)");
b.Property<string>("ProposedAction")
.IsRequired()
.HasColumnType("text");
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<string>("ReasonSummary")
.IsRequired()
.HasColumnType("text");
b.Property<decimal?>("RiskRewardRatio")
.HasColumnType("decimal(18,4)");
b.Property<string>("RiskTolerance")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<string>("RiskWarning")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Sector")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<decimal>("StopLoss")
.HasColumnType("decimal(18,4)");
b.Property<string>("Symbol")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("character varying(30)");
b.Property<decimal>("TakeProfit")
.HasColumnType("decimal(18,4)");
b.Property<string>("TakeProfitTargets")
.HasColumnType("text");
b.Property<string>("TechnicalRationale")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Timeframe")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("character varying(20)");
b.Property<int>("Type")
.HasColumnType("integer");
b.Property<int>("VixRegime")
.HasColumnType("integer");
b.Property<decimal>("VixValue")
.HasColumnType("decimal(18,4)");
b.Property<double>("WinRate")
.HasColumnType("double precision");
b.HasKey("Id");
b.HasIndex("ExpiresAt");
b.HasIndex("Isin");
b.ToTable("TradeProposals");
b.ToTable("trade_proposals");
});
#pragma warning restore 612, 618
}