feat(core): add shared DTOs, MqttTopics constants, DatabaseBootstrapper, and ManagedMqttClient extensions
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FinlyticCore.Dtos.TechnicalAnalysis;
|
||||
|
||||
/// <summary>
|
||||
/// Execution context supplied to pattern detectors and strategy evaluators containing multi-timeframe candles and indicators.
|
||||
/// </summary>
|
||||
public class TechnicalContext
|
||||
{
|
||||
public string Isin { get; init; } = string.Empty;
|
||||
public string Symbol { get; init; } = string.Empty;
|
||||
public string Timeframe { get; init; } = "15m";
|
||||
public DateTime TimestampUtc { get; init; } = DateTime.UtcNow;
|
||||
public decimal CurrentPrice { get; init; }
|
||||
public decimal CurrentSpread { get; init; }
|
||||
public bool IsSpreadVolatile { get; init; }
|
||||
public decimal CurrentAtr { get; init; }
|
||||
public MarketRegime Regime { get; init; } = MarketRegime.LowVolatilityRangebound;
|
||||
|
||||
/// <summary>
|
||||
/// Multi-timeframe historical candles (e.g. "1m", "5m", "15m", "1h", "1d").
|
||||
/// </summary>
|
||||
public Dictionary<string, IReadOnlyList<CandleDto>> MultiTimeframeCandles { get; init; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Pre-calculated mathematical indicator values for the primary timeframe.
|
||||
/// </summary>
|
||||
public Dictionary<string, decimal> Indicators { get; init; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Per-run overrides for a strategy's tunable indicator parameters (e.g. <c>"MeanReversion.RsiOversold"</c>),
|
||||
/// keyed by <c>"{StrategyKey}.{ParameterName}"</c> so a single context could in principle carry overrides
|
||||
/// for more than one strategy without name collisions. Always empty for live scanning
|
||||
/// (<c>TechnicalScoringEngine</c> never populates this - Rules.md §4: no silent behavior change to live
|
||||
/// trade generation as a side effect of a backtesting feature); populated only by
|
||||
/// <c>FinlyticSimulation.Engine.HistoricalReplayRunner</c> from <c>BacktestRequestDto.StrategyParameters</c>,
|
||||
/// so per-asset/per-strategy tuning is opt-in and scoped to backtesting. See <see cref="GetParameter"/>.
|
||||
/// </summary>
|
||||
public Dictionary<string, decimal> ParameterOverrides { get; init; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a tunable strategy parameter: the override in <see cref="ParameterOverrides"/> under
|
||||
/// <c>"{strategyKey}.{parameterName}"</c> if present, otherwise <paramref name="defaultValue"/> (the
|
||||
/// strategy's own hardcoded default, unchanged from before parametrization existed).
|
||||
/// </summary>
|
||||
public decimal GetParameter(string strategyKey, string parameterName, decimal defaultValue)
|
||||
{
|
||||
return ParameterOverrides.TryGetValue($"{strategyKey}.{parameterName}", out var v) ? v : defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the candles for a specific timeframe (defaults to empty list if not found).
|
||||
/// </summary>
|
||||
public IReadOnlyList<CandleDto> GetCandles(string timeframe)
|
||||
{
|
||||
if (MultiTimeframeCandles.TryGetValue(timeframe, out var list))
|
||||
{
|
||||
return list;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the primary timeframe candle sequence.
|
||||
/// </summary>
|
||||
public IReadOnlyList<CandleDto> PrimaryCandles => GetCandles(Timeframe);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific indicator value or null if not computed.
|
||||
/// </summary>
|
||||
public decimal? GetIndicator(string key)
|
||||
{
|
||||
if (Indicators.TryGetValue(key, out var val))
|
||||
{
|
||||
return val;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user