feat(engine): add FinlyticEngine microservice with trade lifecycle, AI reasoning gate, composite scoring, and unit tests
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using FinlyticCore.Dtos.TechnicalAnalysis;
|
||||
using FinlyticCore.Dtos.Trading;
|
||||
|
||||
namespace FinlyticEngine.Database.Entities;
|
||||
|
||||
[Table("engine_trades")]
|
||||
public class EngineTradeEntity
|
||||
{
|
||||
[Key]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
public Guid ProposalId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Owner of this trade. Every read and every mutation is scoped to this value inside FinlyticEngine so a
|
||||
/// user can never see or modify another user's positions. The value originates exclusively from the JWT
|
||||
/// claim in FinlyticBackend and is never taken from a client-supplied payload.
|
||||
/// A single proposal is a system-wide opportunity: several users may each accept it, which produces one
|
||||
/// independent trade per user, all sharing the same <see cref="ProposalId"/>.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public Guid UserId { get; set; }
|
||||
|
||||
[Required]
|
||||
[MaxLength(20)]
|
||||
public string UnderlyingIsin { get; set; } = string.Empty;
|
||||
|
||||
[MaxLength(30)]
|
||||
public string Symbol { get; set; } = string.Empty;
|
||||
|
||||
[MaxLength(20)]
|
||||
public string? DerivativeIsin { get; set; }
|
||||
|
||||
[MaxLength(20)]
|
||||
public string? DerivativeWkn { get; set; }
|
||||
|
||||
public ExecutionMode ExecutionMode { get; set; } = ExecutionMode.ManualTradeRepublic;
|
||||
|
||||
public InstrumentCategoryType InstrumentType { get; set; } = InstrumentCategoryType.Stock;
|
||||
|
||||
public SignalDirection Direction { get; set; } = SignalDirection.Buy;
|
||||
|
||||
public TradeStatus Status { get; set; } = TradeStatus.Proposed;
|
||||
|
||||
[Column(TypeName = "decimal(18,4)")]
|
||||
public decimal AverageBuyIn { get; set; }
|
||||
|
||||
[Column(TypeName = "decimal(18,4)")]
|
||||
public decimal TotalQuantity { get; set; }
|
||||
|
||||
[Column(TypeName = "decimal(18,4)")]
|
||||
public decimal InitialStopLoss { get; set; }
|
||||
|
||||
[Column(TypeName = "decimal(18,4)")]
|
||||
public decimal CurrentStopLoss { get; set; }
|
||||
|
||||
[Column(TypeName = "decimal(18,4)")]
|
||||
public decimal CurrentPrice { get; set; }
|
||||
|
||||
[Column(TypeName = "decimal(18,4)")]
|
||||
public decimal TakeProfit1 { get; set; }
|
||||
|
||||
[Column(TypeName = "decimal(18,4)")]
|
||||
public decimal TakeProfit2 { get; set; }
|
||||
|
||||
[Column(TypeName = "decimal(18,4)")]
|
||||
public decimal? TakeProfitRunner { get; set; }
|
||||
|
||||
[Column(TypeName = "decimal(18,4)")]
|
||||
public decimal RealizedPnlEur { get; set; }
|
||||
|
||||
[Column(TypeName = "decimal(18,4)")]
|
||||
public decimal TotalFeesEur { get; set; }
|
||||
|
||||
public ExitPlan ExitPlan { get; set; } = null!;
|
||||
|
||||
public string ScoreBreakdownJson { get; set; } = "{}";
|
||||
|
||||
[Required]
|
||||
public DateTime OpenedAtUtc { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public DateTime? ClosedAtUtc { get; set; }
|
||||
|
||||
[Required]
|
||||
public DateTime LastUpdatedAtUtc { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public List<EngineTradeFillEntity> Fills { get; set; } = new();
|
||||
}
|
||||
Reference in New Issue
Block a user