feat(technicals): add technical analysis microservice with indicator engines, pattern detectors, and strategies
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using FinlyticCore.Database;
|
||||
using FinlyticCore.Dtos.TechnicalAnalysis;
|
||||
using FinlyticCore.Entities.Settings;
|
||||
using FinlyticTechnicals.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace FinlyticTechnicals.Database;
|
||||
|
||||
public class TechnicalAnalysisDbContext : DbContext, ISettingsDbContext
|
||||
{
|
||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
WriteIndented = false
|
||||
};
|
||||
|
||||
public TechnicalAnalysisDbContext(DbContextOptions<TechnicalAnalysisDbContext> options) : base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public DbSet<SettingEntity> DynamicSettings => Set<SettingEntity>();
|
||||
public DbSet<FtaCandleEntity> FtaCandles => Set<FtaCandleEntity>();
|
||||
public DbSet<FtaTechnicalSetupEntity> FtaTechnicalSetups => Set<FtaTechnicalSetupEntity>();
|
||||
public DbSet<FtaDetectedPatternEntity> FtaDetectedPatterns => Set<FtaDetectedPatternEntity>();
|
||||
public DbSet<FtaMonitoredUniverseAssetEntity> MonitoredUniverseAssets => Set<FtaMonitoredUniverseAssetEntity>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
// 1. Settings Table
|
||||
modelBuilder.Entity<SettingEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id);
|
||||
entity.HasIndex(e => e.Key).IsUnique();
|
||||
});
|
||||
|
||||
// 2. FTA Candles Table & Composite Time-Series Index
|
||||
modelBuilder.Entity<FtaCandleEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id);
|
||||
entity.HasIndex(e => new { e.Isin, e.Timeframe, e.TimestampUtc });
|
||||
entity.HasIndex(e => e.TimestampUtc);
|
||||
});
|
||||
|
||||
// 3. JSONB Value Converters for Complex Types
|
||||
var exitPlanConverter = new ValueConverter<ExitPlan, string>(
|
||||
v => JsonSerializer.Serialize(v, JsonOptions),
|
||||
v => JsonSerializer.Deserialize<ExitPlan>(v, JsonOptions) ?? new ExitPlan(ExitStrategyType.FixedSingleTarget, 0m, new List<TakeProfitStage>(), null, null, null, null)
|
||||
);
|
||||
|
||||
var patternsConverter = new ValueConverter<List<PatternResultDto>, string>(
|
||||
v => JsonSerializer.Serialize(v, JsonOptions),
|
||||
v => JsonSerializer.Deserialize<List<PatternResultDto>>(v, JsonOptions) ?? new List<PatternResultDto>()
|
||||
);
|
||||
|
||||
var indicatorSnapshotConverter = new ValueConverter<Dictionary<string, decimal>, string>(
|
||||
v => JsonSerializer.Serialize(v, JsonOptions),
|
||||
v => JsonSerializer.Deserialize<Dictionary<string, decimal>>(v, JsonOptions) ?? new Dictionary<string, decimal>()
|
||||
);
|
||||
|
||||
var extraDataConverter = new ValueConverter<Dictionary<string, object>?, string>(
|
||||
v => v == null ? "{}" : JsonSerializer.Serialize(v, JsonOptions),
|
||||
v => string.IsNullOrWhiteSpace(v) ? null : JsonSerializer.Deserialize<Dictionary<string, object>>(v, JsonOptions)
|
||||
);
|
||||
|
||||
// 4. FTA Technical Setups Table & JSONB mappings
|
||||
modelBuilder.Entity<FtaTechnicalSetupEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.SetupId);
|
||||
entity.HasIndex(e => new { e.Isin, e.IsActive, e.ExpiresAtUtc });
|
||||
entity.HasIndex(e => e.CreatedAtUtc);
|
||||
entity.HasIndex(e => e.QualityScore);
|
||||
entity.HasIndex(e => e.IsTopPick);
|
||||
entity.HasIndex(e => new { e.IsActive, e.IsTopPick, e.QualityScore });
|
||||
|
||||
|
||||
entity.Property(e => e.ExitPlan)
|
||||
.HasColumnType("jsonb")
|
||||
.HasConversion(exitPlanConverter);
|
||||
|
||||
entity.Property(e => e.TriggeringPatterns)
|
||||
.HasColumnType("jsonb")
|
||||
.HasConversion(patternsConverter);
|
||||
|
||||
entity.Property(e => e.IndicatorSnapshot)
|
||||
.HasColumnType("jsonb")
|
||||
.HasConversion(indicatorSnapshotConverter);
|
||||
});
|
||||
|
||||
// 5. FTA Detected Patterns Table & JSONB mappings
|
||||
modelBuilder.Entity<FtaDetectedPatternEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id);
|
||||
entity.HasIndex(e => new { e.Isin, e.DetectedAtUtc });
|
||||
entity.HasIndex(e => e.PatternType);
|
||||
entity.HasIndex(e => e.QualityScore);
|
||||
|
||||
entity.Property(e => e.ExtraData)
|
||||
.HasColumnType("jsonb")
|
||||
.HasConversion(extraDataConverter);
|
||||
});
|
||||
|
||||
// 6. Monitored Universe Assets Table (persisted backing store for TechnicalUniverseManager, cleared on
|
||||
// every service startup - see FtaMonitoredUniverseAssetEntity's doc comment)
|
||||
modelBuilder.Entity<FtaMonitoredUniverseAssetEntity>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Isin);
|
||||
entity.HasIndex(e => e.Source);
|
||||
entity.HasIndex(e => e.ExpiresAtUtc);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class TechnicalAnalysisDbContextFactory : IDesignTimeDbContextFactory<TechnicalAnalysisDbContext>
|
||||
{
|
||||
public TechnicalAnalysisDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
var optionsBuilder = new DbContextOptionsBuilder<TechnicalAnalysisDbContext>();
|
||||
optionsBuilder.UseNpgsql("Host=localhost;Database=finlytic_ta;Username=postgres;Password=postgres");
|
||||
return new TechnicalAnalysisDbContext(optionsBuilder.Options);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user