105 lines
4.2 KiB
C#
105 lines
4.2 KiB
C#
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
|
||
);
|