feat(simulation): add quant simulation microservice with virtual backtest broker and replay engine

This commit is contained in:
2026-08-24 21:36:20 +02:00
parent f43ce2b7e9
commit a4959658a2
22 changed files with 2600 additions and 0 deletions
@@ -0,0 +1,63 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using FinlyticCore.Dtos.Simulation;
namespace FinlyticSimulation.Database.Entities;
[Table("simulation_runs")]
public class SimulationRunEntity
{
[Key]
public Guid Id { get; set; } = Guid.NewGuid();
[Required]
[MaxLength(20)]
public string Isin { get; set; } = string.Empty;
[MaxLength(30)]
public string Symbol { get; set; } = string.Empty;
[Required]
[MaxLength(50)]
public string StrategyKey { get; set; } = string.Empty;
[Required]
[MaxLength(10)]
public string Timeframe { get; set; } = "15m";
public DateTime StartDateUtc { get; set; }
public DateTime EndDateUtc { get; set; }
[Column(TypeName = "decimal(18,4)")]
public decimal StartingCapital { get; set; }
public int TotalTrades { get; set; }
public int WinningTrades { get; set; }
public int LosingTrades { get; set; }
[Column(TypeName = "decimal(6,2)")]
public decimal WinRatePercent { get; set; }
[Column(TypeName = "decimal(8,4)")]
public decimal ProfitFactor { get; set; }
[Column(TypeName = "decimal(6,2)")]
public decimal MaxDrawdownPercent { get; set; }
[Column(TypeName = "decimal(8,2)")]
public decimal TotalReturnPercent { get; set; }
[Column(TypeName = "decimal(18,4)")]
public decimal ExpectancyEur { get; set; }
[Column(TypeName = "decimal(8,4)")]
public decimal SharpeRatio { get; set; }
public BacktestReportDto ReportJson { get; set; } = null!;
public DateTime CreatedAtUtc { get; set; } = DateTime.UtcNow;
}
@@ -0,0 +1,44 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace FinlyticSimulation.Database.Entities;
[Table("simulation_strategy_matrix")]
public class SimulationStrategyMatrixEntity
{
[Required]
[MaxLength(20)]
public string Isin { get; set; } = string.Empty;
[Required]
[MaxLength(50)]
public string StrategyKey { get; set; } = string.Empty;
[Required]
[MaxLength(10)]
public string Timeframe { get; set; } = "15m";
public int SampleTradesCount { get; set; }
[Column(TypeName = "decimal(6,2)")]
public decimal WinRatePercent { get; set; }
[Column(TypeName = "decimal(8,4)")]
public decimal ProfitFactor { get; set; }
[Column(TypeName = "decimal(6,2)")]
public decimal MaxDrawdownPercent { get; set; }
[Column(TypeName = "decimal(5,2)")]
public decimal ReliabilityScore { get; set; } // 0 - 100
public bool IsApproved { get; set; } = true;
[MaxLength(30)]
public string RecommendedAction { get; set; } = "NEUTRAL"; // "BOOST_SCORE", "NEUTRAL", "VETO_DISABLE"
public Guid? LastBacktestRunId { get; set; }
public DateTime UpdatedAtUtc { get; set; } = DateTime.UtcNow;
}
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace FinlyticSimulation.Database.Entities;
/// <summary>
/// A saved, named-by-(Isin, StrategyKey) set of tunable indicator parameter overrides (see
/// <c>TechnicalContext.ParameterOverrides</c>), so a parameter set found useful via repeated backtest
/// experimentation can be reused without retyping it every time. Purely a backtesting-side convenience - never
/// read by live scanning (<c>FinlyticTechnicals.Services.TechnicalScoringEngine</c> never queries this table).
/// </summary>
[Table("simulation_strategy_parameters")]
public class SimulationStrategyParameterEntity
{
[Required]
[MaxLength(20)]
public string Isin { get; set; } = string.Empty;
[Required]
[MaxLength(50)]
public string StrategyKey { get; set; } = string.Empty;
/// <summary>Keyed by <c>"{StrategyKey}.{ParameterName}"</c>, matching <c>TechnicalContext.ParameterOverrides</c> 1:1.</summary>
public Dictionary<string, decimal> Parameters { get; set; } = new();
public DateTime UpdatedAtUtc { get; set; } = DateTime.UtcNow;
}