100 lines
3.5 KiB
C#
100 lines
3.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using FinlyticCore.Dtos.TechnicalAnalysis;
|
|
using FinlyticCore.Dtos.Trading;
|
|
using FinlyticEngine.Database.Entities;
|
|
|
|
namespace FinlyticEngine.Tests.TestSupport;
|
|
|
|
/// <summary>
|
|
/// Small builder helpers for the entities used across the TradeLifecycleService tenant-boundary tests, to
|
|
/// keep individual test methods focused on the behavior under test rather than entity plumbing.
|
|
/// </summary>
|
|
public static class TestData
|
|
{
|
|
public static ExitPlan SimpleExitPlan(decimal stopLoss = 90m, decimal takeProfit = 110m) => new(
|
|
StrategyType: ExitStrategyType.FixedSingleTarget,
|
|
InitialStopLoss: stopLoss,
|
|
TakeProfitStages: new List<TakeProfitStage>
|
|
{
|
|
new(1, takeProfit, 100m, 1m, "Test stage")
|
|
});
|
|
|
|
public static AiValidationResultDto ApprovedAiValidation() => new(
|
|
IsApproved: true,
|
|
Confidence: 0.9m,
|
|
Source: ValidationSource.Ai,
|
|
ThesisSummary: "Test thesis",
|
|
InvalidationReason: "",
|
|
KeyCatalysts: new List<string>(),
|
|
IdentifiedRisks: new List<string>());
|
|
|
|
/// <summary>
|
|
/// Builds an active, non-expired trade proposal ("system-wide opportunity") ready to be accepted.
|
|
/// </summary>
|
|
public static EngineTradeProposalEntity ActiveProposal(
|
|
string isin = "US0378331005",
|
|
decimal entryPrice = 100m,
|
|
decimal stopLoss = 90m,
|
|
bool isActive = true,
|
|
DateTime? expiresAtUtc = null)
|
|
{
|
|
return new EngineTradeProposalEntity
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
UnderlyingIsin = isin,
|
|
Symbol = "AAPL",
|
|
StrategyKey = "TestStrategy",
|
|
Direction = SignalDirection.Buy,
|
|
QualityScore = 80m,
|
|
CompositeScore = 80m,
|
|
CurrentPrice = entryPrice,
|
|
EntryPrice = entryPrice,
|
|
StopLoss = stopLoss,
|
|
TakeProfit1 = entryPrice * 1.1m,
|
|
RiskRewardRatio = 2m,
|
|
ExitPlan = SimpleExitPlan(stopLoss, entryPrice * 1.1m),
|
|
SelectedDerivative = null,
|
|
AiValidation = ApprovedAiValidation(),
|
|
IsActive = isActive,
|
|
CreatedAtUtc = DateTime.UtcNow,
|
|
ExpiresAtUtc = expiresAtUtc ?? DateTime.UtcNow.AddHours(24)
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Builds an active trade owned by <paramref name="userId"/>, optionally linked to a proposal.
|
|
/// </summary>
|
|
public static EngineTradeEntity ActiveTrade(
|
|
Guid userId,
|
|
Guid? proposalId = null,
|
|
string isin = "US0378331005",
|
|
decimal averageBuyIn = 100m,
|
|
decimal stopLoss = 90m,
|
|
TradeStatus status = TradeStatus.Active)
|
|
{
|
|
return new EngineTradeEntity
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
UserId = userId,
|
|
ProposalId = proposalId ?? Guid.Empty,
|
|
UnderlyingIsin = isin,
|
|
Symbol = "AAPL",
|
|
ExecutionMode = ExecutionMode.ManualTradeRepublic,
|
|
InstrumentType = InstrumentCategoryType.Stock,
|
|
Direction = SignalDirection.Buy,
|
|
Status = status,
|
|
AverageBuyIn = averageBuyIn,
|
|
TotalQuantity = 1m,
|
|
InitialStopLoss = stopLoss,
|
|
CurrentStopLoss = stopLoss,
|
|
CurrentPrice = averageBuyIn,
|
|
TakeProfit1 = averageBuyIn * 1.1m,
|
|
TakeProfit2 = averageBuyIn * 1.2m,
|
|
ExitPlan = SimpleExitPlan(stopLoss, averageBuyIn * 1.1m),
|
|
OpenedAtUtc = DateTime.UtcNow,
|
|
LastUpdatedAtUtc = DateTime.UtcNow
|
|
};
|
|
}
|
|
}
|