Fix graph

This commit is contained in:
2025-11-25 11:03:52 +07:00
parent 6376e13b07
commit 4b5c1c5ce0
6 changed files with 140 additions and 66 deletions

View File

@@ -208,6 +208,10 @@ public enum IndicatorType
**Update IndicatorRequest.cs:** **Update IndicatorRequest.cs:**
- Add any new parameter properties to match LightIndicator - Add any new parameter properties to match LightIndicator
**Update DataController.cs:**
- Add any new parameter properties to the `MapScenarioRequestToScenario()` method's `IndicatorBase` initialization
- This ensures API requests with indicator parameters are properly mapped to domain objects
**Update ScenarioHelpers.cs:** **Update ScenarioHelpers.cs:**
- Add case to `BuildIndicator()` method: `IndicatorType.{EnumName} => new {IndicatorName}(indicator.Name, {parameters})` - Add case to `BuildIndicator()` method: `IndicatorType.{EnumName} => new {IndicatorName}(indicator.Name, {parameters})`
- Add case to `GetSignalType()` method: `IndicatorType.{EnumName} => SignalType.{Type}` - Add case to `GetSignalType()` method: `IndicatorType.{EnumName} => SignalType.{Type}`
@@ -219,6 +223,10 @@ public enum IndicatorType
- Update LightIndicator creation in bundle job creation to include all new properties - Update LightIndicator creation in bundle job creation to include all new properties
- Ensure all indicator parameters are properly mapped from requests - Ensure all indicator parameters are properly mapped from requests
**Update DataController.cs:**
- Update `MapScenarioRequestToScenario()` method to include all new parameters in the `IndicatorBase` initialization
- Ensure all properties from `IndicatorRequest` are properly mapped to `IndicatorBase` (Period, StDev, KFactor, DFactor, TenkanPeriods, etc.)
**Update GeneticService.cs:** **Update GeneticService.cs:**
- Add default values to `DefaultIndicatorValues`: `[IndicatorType.{EnumName}] = new() { {param_mappings} }` - Add default values to `DefaultIndicatorValues`: `[IndicatorType.{EnumName}] = new() { {param_mappings} }`
- Add parameter ranges to `IndicatorParameterRanges`: `[IndicatorType.{EnumName}] = new() { {param_ranges} }` - Add parameter ranges to `IndicatorParameterRanges`: `[IndicatorType.{EnumName}] = new() { {param_ranges} }`
@@ -502,6 +510,7 @@ public class BollingerBandsVolatilityProtection : BollingerBandsBase { /* Volati
- [ ] IndicatorRequest.cs properties added - [ ] IndicatorRequest.cs properties added
- [ ] ScenarioHelpers.cs BuildIndicator and BaseToLight methods updated - [ ] ScenarioHelpers.cs BuildIndicator and BaseToLight methods updated
- [ ] BacktestJobService.cs LightIndicator mapping updated - [ ] BacktestJobService.cs LightIndicator mapping updated
- [ ] DataController.cs MapScenarioRequestToScenario method updated
- [ ] GeneticService.cs configurations updated (defaults, ranges, mappings) - [ ] GeneticService.cs configurations updated (defaults, ranges, mappings)
- [ ] Frontend CustomScenario.tsx updated for new parameters - [ ] Frontend CustomScenario.tsx updated for new parameters
- [ ] Frontend TradeChart.tsx updated for visualization if needed - [ ] Frontend TradeChart.tsx updated for visualization if needed

View File

@@ -17,7 +17,6 @@ using Managing.Domain.Trades;
using MediatR; using MediatR;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using static Managing.Common.Enums; using static Managing.Common.Enums;
using DailySnapshot = Managing.Api.Models.Responses.DailySnapshot; using DailySnapshot = Managing.Api.Models.Responses.DailySnapshot;
@@ -831,9 +830,18 @@ public class DataController : ControllerBase
SlowPeriods = indicatorRequest.SlowPeriods, SlowPeriods = indicatorRequest.SlowPeriods,
SignalPeriods = indicatorRequest.SignalPeriods, SignalPeriods = indicatorRequest.SignalPeriods,
Multiplier = indicatorRequest.Multiplier, Multiplier = indicatorRequest.Multiplier,
StDev = indicatorRequest.StDev,
SmoothPeriods = indicatorRequest.SmoothPeriods, SmoothPeriods = indicatorRequest.SmoothPeriods,
StochPeriods = indicatorRequest.StochPeriods, StochPeriods = indicatorRequest.StochPeriods,
CyclePeriods = indicatorRequest.CyclePeriods CyclePeriods = indicatorRequest.CyclePeriods,
KFactor = indicatorRequest.KFactor,
DFactor = indicatorRequest.DFactor,
TenkanPeriods = indicatorRequest.TenkanPeriods,
KijunPeriods = indicatorRequest.KijunPeriods,
SenkouBPeriods = indicatorRequest.SenkouBPeriods,
OffsetPeriods = indicatorRequest.OffsetPeriods,
SenkouOffset = indicatorRequest.SenkouOffset,
ChikouOffset = indicatorRequest.ChikouOffset
}; };
scenario.AddIndicator(indicator); scenario.AddIndicator(indicator);

View File

@@ -71,40 +71,40 @@ public static class ScenarioHelpers
{ {
IIndicator result = indicator.Type switch IIndicator result = indicator.Type switch
{ {
IndicatorType.StDev => new StDevContext(indicator.Name, indicator.Period.Value), IndicatorType.StDev => new StDevContext(indicator.Name, indicator.Period ?? 14),
IndicatorType.RsiDivergence => new RsiDivergenceIndicatorBase(indicator.Name, IndicatorType.RsiDivergence => new RsiDivergenceIndicatorBase(indicator.Name,
indicator.Period.Value), indicator.Period ?? 14),
IndicatorType.RsiDivergenceConfirm => new RsiDivergenceConfirmIndicatorBase(indicator.Name, IndicatorType.RsiDivergenceConfirm => new RsiDivergenceConfirmIndicatorBase(indicator.Name,
indicator.Period.Value), indicator.Period ?? 14),
IndicatorType.MacdCross => new MacdCrossIndicatorBase(indicator.Name, IndicatorType.MacdCross => new MacdCrossIndicatorBase(indicator.Name,
indicator.FastPeriods.Value, indicator.SlowPeriods.Value, indicator.SignalPeriods.Value), indicator.FastPeriods ?? 12, indicator.SlowPeriods ?? 26, indicator.SignalPeriods ?? 9),
IndicatorType.EmaCross => new EmaCrossIndicatorBase(indicator.Name, indicator.Period.Value), IndicatorType.EmaCross => new EmaCrossIndicatorBase(indicator.Name, indicator.Period ?? 14),
IndicatorType.DualEmaCross => new DualEmaCrossIndicatorBase(indicator.Name, IndicatorType.DualEmaCross => new DualEmaCrossIndicatorBase(indicator.Name,
indicator.FastPeriods.Value, indicator.SlowPeriods.Value), indicator.FastPeriods ?? 12, indicator.SlowPeriods ?? 26),
IndicatorType.ThreeWhiteSoldiers => new ThreeWhiteSoldiersIndicatorBase(indicator.Name, IndicatorType.ThreeWhiteSoldiers => new ThreeWhiteSoldiersIndicatorBase(indicator.Name,
indicator.Period.Value), indicator.Period ?? 14),
IndicatorType.SuperTrend => new SuperTrendIndicatorBase(indicator.Name, IndicatorType.SuperTrend => new SuperTrendIndicatorBase(indicator.Name,
indicator.Period.Value, indicator.Multiplier.Value), indicator.Period ?? 14, indicator.Multiplier ?? 3.0),
IndicatorType.ChandelierExit => new ChandelierExitIndicatorBase(indicator.Name, IndicatorType.ChandelierExit => new ChandelierExitIndicatorBase(indicator.Name,
indicator.Period.Value, indicator.Multiplier.Value), indicator.Period ?? 14, indicator.Multiplier ?? 3.0),
IndicatorType.EmaTrend => new EmaTrendIndicatorBase(indicator.Name, indicator.Period.Value), IndicatorType.EmaTrend => new EmaTrendIndicatorBase(indicator.Name, indicator.Period ?? 14),
IndicatorType.StochRsiTrend => new StochRsiTrendIndicatorBase(indicator.Name, IndicatorType.StochRsiTrend => new StochRsiTrendIndicatorBase(indicator.Name,
indicator.Period.Value, indicator.StochPeriods.Value, indicator.SignalPeriods.Value, indicator.Period ?? 14, indicator.StochPeriods ?? 14, indicator.SignalPeriods ?? 9,
indicator.SmoothPeriods.Value), indicator.SmoothPeriods ?? 3),
IndicatorType.StochasticCross => new StochasticCrossIndicator(indicator.Name, IndicatorType.StochasticCross => new StochasticCrossIndicator(indicator.Name,
indicator.StochPeriods.Value, indicator.SignalPeriods.Value, indicator.SmoothPeriods.Value, indicator.StochPeriods ?? 14, indicator.SignalPeriods ?? 3, indicator.SmoothPeriods ?? 3,
indicator.KFactor ?? 3.0, indicator.DFactor ?? 2.0), indicator.KFactor ?? 3.0, indicator.DFactor ?? 2.0),
IndicatorType.Stc => new StcIndicatorBase(indicator.Name, indicator.CyclePeriods.Value, IndicatorType.Stc => new StcIndicatorBase(indicator.Name, indicator.CyclePeriods ?? 10,
indicator.FastPeriods.Value, indicator.SlowPeriods.Value), indicator.FastPeriods ?? 12, indicator.SlowPeriods ?? 26),
IndicatorType.LaggingStc => new LaggingSTC(indicator.Name, indicator.CyclePeriods.Value, IndicatorType.LaggingStc => new LaggingSTC(indicator.Name, indicator.CyclePeriods ?? 10,
indicator.FastPeriods.Value, indicator.SlowPeriods.Value), indicator.FastPeriods ?? 12, indicator.SlowPeriods ?? 26),
IndicatorType.SuperTrendCrossEma => new SuperTrendCrossEma(indicator.Name, IndicatorType.SuperTrendCrossEma => new SuperTrendCrossEma(indicator.Name,
indicator.Period.Value, indicator.Multiplier.Value), indicator.Period ?? 14, indicator.Multiplier ?? 3.0),
IndicatorType.BollingerBandsPercentBMomentumBreakout => new BollingerBandsPercentBMomentumBreakout( IndicatorType.BollingerBandsPercentBMomentumBreakout => new BollingerBandsPercentBMomentumBreakout(
indicator.Name, indicator.Name,
indicator.Period.Value, indicator.StDev.Value), indicator.Period ?? 20, indicator.StDev ?? 2.0),
IndicatorType.BollingerBandsVolatilityProtection => new BollingerBandsVolatilityProtection(indicator.Name, IndicatorType.BollingerBandsVolatilityProtection => new BollingerBandsVolatilityProtection(indicator.Name,
indicator.Period.Value, indicator.StDev.Value), indicator.Period ?? 20, indicator.StDev ?? 2.0),
IndicatorType.IchimokuKumoTrend => new IchimokuKumoTrend(indicator.Name, IndicatorType.IchimokuKumoTrend => new IchimokuKumoTrend(indicator.Name,
indicator.TenkanPeriods ?? 9, indicator.TenkanPeriods ?? 9,
indicator.KijunPeriods ?? 26, indicator.KijunPeriods ?? 26,

View File

@@ -937,8 +937,9 @@ public static class TradingBox
var buildedIndicator = ScenarioHelpers.BuildIndicator(ScenarioHelpers.BaseToLight(indicator)); var buildedIndicator = ScenarioHelpers.BuildIndicator(ScenarioHelpers.BaseToLight(indicator));
indicatorsValues[indicator.Type] = buildedIndicator.GetIndicatorValues(candles); indicatorsValues[indicator.Type] = buildedIndicator.GetIndicatorValues(candles);
} }
catch (Exception) catch (Exception ex)
{ {
throw;
// Removed logging for performance in static method // Removed logging for performance in static method
// Consider adding logging back if error handling is needed // Consider adding logging back if error handling is needed
} }

View File

@@ -66,9 +66,18 @@ const BacktestRowDetails: React.FC<IBacktestRowDetailsProps> = ({
slowPeriods: indicator.slowPeriods, slowPeriods: indicator.slowPeriods,
signalPeriods: indicator.signalPeriods, signalPeriods: indicator.signalPeriods,
multiplier: indicator.multiplier, multiplier: indicator.multiplier,
stDev: indicator.stDev,
smoothPeriods: indicator.smoothPeriods, smoothPeriods: indicator.smoothPeriods,
stochPeriods: indicator.stochPeriods, stochPeriods: indicator.stochPeriods,
cyclePeriods: indicator.cyclePeriods cyclePeriods: indicator.cyclePeriods,
kFactor: indicator.kFactor,
dFactor: indicator.dFactor,
tenkanPeriods: indicator.tenkanPeriods,
kijunPeriods: indicator.kijunPeriods,
senkouBPeriods: indicator.senkouBPeriods,
offsetPeriods: indicator.offsetPeriods,
senkouOffset: indicator.senkouOffset,
chikouOffset: indicator.chikouOffset
})) || [], })) || [],
loopbackPeriod: backtest.config.scenario.loopbackPeriod loopbackPeriod: backtest.config.scenario.loopbackPeriod
} : undefined } : undefined
@@ -76,7 +85,6 @@ const BacktestRowDetails: React.FC<IBacktestRowDetailsProps> = ({
return await dataClient.data_GetCandlesWithIndicators(request); return await dataClient.data_GetCandlesWithIndicators(request);
}, },
enabled: !backtest.candles || backtest.candles.length === 0, // Only run query if no candles exist
staleTime: 5 * 60 * 1000, // 5 minutes staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000, // 10 minutes (formerly cacheTime) gcTime: 10 * 60 * 1000, // 10 minutes (formerly cacheTime)
}); });

View File

@@ -565,47 +565,6 @@ const TradeChart = ({
lowerBandSeries.setData(lowerBandData) lowerBandSeries.setData(lowerBandData)
} }
// Display Bollinger Bands on price chart for Volatility Protection
if (indicatorsValues?.BollingerBandsVolatilityProtection != null) {
const upperBandSeries = chart.current.addLineSeries({
color: '#FF6B6B', // Lighter red for volatility protection bands
lineWidth: 1,
priceLineVisible: false,
priceLineWidth: 1,
title: 'Volatility Protection Upper Band',
pane: 0,
lineStyle: LineStyle.Dotted,
})
const upperBandData = indicatorsValues.BollingerBandsVolatilityProtection.bollingerBands?.map((w) => {
return {
time: moment(w.date).unix(),
value: w.upperBand,
}
})
// @ts-ignore
upperBandSeries.setData(upperBandData)
const lowerBandSeries = chart.current.addLineSeries({
color: '#4ECDC4', // Teal for volatility protection bands
lineWidth: 1,
priceLineVisible: false,
priceLineWidth: 1,
title: 'Volatility Protection Lower Band',
pane: 0,
lineStyle: LineStyle.Dotted,
})
const lowerBandData = indicatorsValues.BollingerBandsVolatilityProtection.bollingerBands?.map((w) => {
return {
time: moment(w.date).unix(),
value: w.lowerBand,
}
})
// @ts-ignore
lowerBandSeries.setData(lowerBandData)
}
if (markers.length > 0) { if (markers.length > 0) {
series1.current.setMarkers(markers) series1.current.setMarkers(markers)
} }
@@ -674,6 +633,95 @@ const TradeChart = ({
paneCount++ paneCount++
} }
// Display Bollinger Bands Volatility Protection Width on separate pane
if (indicatorsValues?.BollingerBandsVolatilityProtection != null) {
const volatilityWidthSeries = chart.current.addLineSeries({
color: '#8B5CF6', // Purple for volatility width
lineWidth: 2,
priceLineVisible: true,
priceLineWidth: 1,
title: 'Volatility Width (BB %)',
pane: paneCount,
priceFormat: {
minMove: 0.001,
precision: 3,
type: 'price',
},
})
const volatilityWidthData = indicatorsValues.BollingerBandsVolatilityProtection.bollingerBands?.map((w) => {
return {
time: moment(w.date).unix(),
value: w.width,
}
})
// @ts-ignore
volatilityWidthSeries.setData(volatilityWidthData)
// Add confidence range lines (0.02 - 0.10)
const confidenceMinLine = chart.current.addLineSeries({
color: '#16A34A', // Green for confidence range minimum
lineWidth: 1,
priceLineVisible: true,
priceLineWidth: 1,
title: 'Conf Min (2%)',
pane: paneCount,
lineStyle: LineStyle.Dashed,
priceFormat: {
minMove: 0.001,
precision: 3,
type: 'price',
},
})
const confidenceMaxLine = chart.current.addLineSeries({
color: '#16A34A', // Green for confidence range maximum
lineWidth: 1,
priceLineVisible: true,
priceLineWidth: 1,
title: 'Conf Max (10%)',
pane: paneCount,
lineStyle: LineStyle.Dashed,
priceFormat: {
minMove: 0.001,
precision: 3,
type: 'price',
},
})
// Create horizontal lines for confidence range
const bollingerBands = indicatorsValues.BollingerBandsVolatilityProtection.bollingerBands
if (bollingerBands && bollingerBands.length > 0) {
const confidenceMinData = [
{
time: moment(bollingerBands[0].date).unix(),
value: 0.02, // Confidence minimum threshold
},
{
time: moment(bollingerBands[bollingerBands.length - 1].date).unix(),
value: 0.02, // Confidence minimum threshold
}
]
// @ts-ignore
confidenceMinLine.setData(confidenceMinData)
const confidenceMaxData = [
{
time: moment(bollingerBands[0].date).unix(),
value: 0.10, // Confidence maximum threshold
},
{
time: moment(bollingerBands[bollingerBands.length - 1].date).unix(),
value: 0.10, // Confidence maximum threshold
}
]
// @ts-ignore
confidenceMaxLine.setData(confidenceMaxData)
}
paneCount++
}
if (indicatorsValues?.LaggingStc != null) { if (indicatorsValues?.LaggingStc != null) {
const laggingStcSeries = chart.current.addBaselineSeries({ const laggingStcSeries = chart.current.addBaselineSeries({
pane: paneCount, pane: paneCount,