Files
Finlytic/FinlyticEngine/Services/Ai/N8nValidationPayloadDtos.cs

105 lines
4.2 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
namespace FinlyticEngine.Services.Ai;
/// <summary>
/// Outgoing request body for the n8n AI trade-validation webhook. Service-local (not FinlyticCore): this
/// shape is an integration detail of <see cref="AiReasoningGateService"/> only, not a cross-service MQTT
/// contract (Rules.md §3 - core placement applies to data shared across services, not to a single service's
/// own outbound HTTP integration). Serialized with <c>JsonNamingPolicy.CamelCase</c>, so every property here
/// reaches n8n as camelCase without needing per-property <c>[JsonPropertyName]</c> attributes.
/// </summary>
public record N8nValidationRequestPayload(
string Instructions,
N8nAssetSection Asset,
N8nTechnicalSetupSection TechnicalSetup,
N8nWatchlistContextSection? WatchlistContext,
N8nSentimentSection Sentiment,
N8nFundamentalsSection Fundamentals,
N8nReliabilitySection? Reliability,
N8nScoreBreakdownSection ScoreBreakdown
);
public record N8nAssetSection(string Isin, string Symbol, decimal CurrentPrice);
public record N8nPatternSection(string Type, string Bias, decimal QualityScore, string Description);
public record N8nTechnicalSetupSection(
string Strategy,
string StrategyName,
string Direction,
decimal Entry,
decimal StopLoss,
decimal TakeProfit1,
decimal RiskRewardRatio,
decimal QualityScore,
string Rationale,
string? MarketRegime,
List<N8nPatternSection> TriggeringPatterns,
Dictionary<string, decimal> IndicatorSnapshot
);
/// <summary>Why FinlyticTechnicals was even scanning this ISIN (see <c>TechnicalUniverseManager</c>).</summary>
public record N8nWatchlistContextSection(string Source, DateTime EnteredAtUtc);
public record N8nSentimentSection(string Label, double WeightedScore, string Trend, string LatestHighlight);
/// <summary>
/// Fundamental data + the two temporal suppression gates (<see cref="Scoring.ScoringResult.PassedEarningsLockout"/>/
/// <see cref="Scoring.ScoringResult.PassedDividendGate"/>). Ratio fields (<c>ReturnOnEquityRatio</c> etc.) are
/// forwarded as raw fractions (e.g. <c>0.15</c> = 15%) exactly as stored, rather than guessing a ×100
/// conversion that could silently misrepresent the source data (Rules.md §4). <see cref="OperatingMarginPercent"/>
/// is the one exception: an honest, explicitly computed ratio (OperatingIncome / TotalRevenue × 100), only
/// populated when both inputs are real numbers.
/// </summary>
public record N8nFundamentalsSection(
decimal? ForwardPe,
decimal? OperatingMarginPercent,
decimal? RevenueGrowthYoYRatio,
decimal? ReturnOnEquityRatio,
decimal? DebtToEquity,
decimal? FreeCashFlow,
string? ConsensusRating,
decimal? PriceTargetMean,
decimal? ShortPercentOfFloatRatio,
int? DaysToEarnings,
bool PassedEarningsLockout,
int? DaysToNextExDividend,
bool PassedDividendGate
);
/// <summary>FinlyticSimulation's backtest verdict for this exact (Isin, StrategyKey) - see <see cref="IAiReasoningGateService"/>.</summary>
public record N8nReliabilitySection(
decimal ReliabilityScore,
decimal WinRatePercent,
decimal ProfitFactor,
int SampleTradeCount,
bool IsStrategyApprovedForAsset,
string RecommendedAction
);
public record N8nScoreBreakdownSection(
decimal CompositeScore,
decimal TechnicalScore,
decimal SentimentScore,
decimal FundamentalScore,
decimal ReliabilityBonus
);
/// <summary>
/// Expected shape of a successful n8n webhook response - deliberately identical field-for-field to
/// <see cref="FinlyticCore.Dtos.Trading.AiValidationResultDto"/> (camelCase JSON) instead of the previous,
/// undocumented ad hoc vocabulary (<c>status</c>/<c>action_recommendation</c>/<c>raw_validation_result.*</c>)
/// that no prompt ever actually specified. <see cref="Confidence"/> is nullable because a validator that
/// declines to give a numeric confidence must not have one fabricated for it (Rules.md §4).
/// </summary>
public record N8nValidationResponsePayload(
bool? IsApproved,
decimal? Confidence,
string? ThesisSummary,
string? InvalidationReason,
List<string>? KeyCatalysts,
List<string>? IdentifiedRisks
);