diff --git a/src/Managing.Application/Trading/TradingService.cs b/src/Managing.Application/Trading/TradingService.cs
index fdf1d49e..274db3dd 100644
--- a/src/Managing.Application/Trading/TradingService.cs
+++ b/src/Managing.Application/Trading/TradingService.cs
@@ -580,7 +580,7 @@ public class TradingService : ITradingService
}
///
- /// Generates signals for a date range using a rolling window approach.
+ /// Generates signals for a date range by running each indicator individually and collecting all signals.
///
private List GenerateSignalsForDateRange(
List candles,
@@ -588,47 +588,47 @@ public class TradingService : ITradingService
Dictionary preCalculatedIndicatorValues)
{
var allSignals = new List();
- var previousSignals = new Dictionary();
var lightScenario = LightScenario.FromScenario(scenario);
- // Use rolling window approach similar to backtests
- const int RollingWindowSize = 600;
- var rollingWindowCandles = new List(RollingWindowSize);
-
- foreach (var candle in candles)
+ // Process each indicator individually to get all signals from each
+ foreach (var lightIndicator in lightScenario.Indicators)
{
- // Maintain rolling window
- if (rollingWindowCandles.Count >= RollingWindowSize)
- {
- rollingWindowCandles.RemoveAt(0);
- }
- rollingWindowCandles.Add(candle);
+ // Build the indicator instance
+ var indicatorInstance = lightIndicator.ToInterface();
- // Only process if we have enough candles for indicators
- if (rollingWindowCandles.Count < 2)
+ // Use pre-calculated indicator values if available
+ List indicatorSignals;
+ if (preCalculatedIndicatorValues != null && preCalculatedIndicatorValues.ContainsKey(lightIndicator.Type))
{
- continue;
+ // Use pre-calculated values to avoid recalculating indicators
+ indicatorSignals = indicatorInstance.Run(candles, preCalculatedIndicatorValues[lightIndicator.Type]);
+ }
+ else
+ {
+ // Normal path: calculate indicators on the fly
+ indicatorSignals = indicatorInstance.Run(candles);
}
- // Generate signal for current position
- var signal = TradingBox.GetSignal(
- rollingWindowCandles,
- lightScenario,
- previousSignals,
- scenario.LookbackPeriod,
- preCalculatedIndicatorValues);
-
- if (signal != null)
+ // Add all signals from this indicator to the collection
+ if (indicatorSignals != null && indicatorSignals.Count > 0)
{
- // Check if this is a new signal (not already in our collection)
- if (!previousSignals.ContainsKey(signal.Identifier))
- {
- allSignals.Add(signal);
- previousSignals[signal.Identifier] = signal;
- }
+ // Filter signals to only include those within the candle date range
+ var firstCandleDate = candles.First().Date;
+ var lastCandleDate = candles.Last().Date;
+
+ var filteredSignals = indicatorSignals
+ .Where(s => s.Date >= firstCandleDate && s.Date <= lastCandleDate)
+ .ToList();
+
+ allSignals.AddRange(filteredSignals);
}
}
- return allSignals.OrderBy(s => s.Date).ToList();
+ // Remove duplicates based on identifier and sort by date
+ return allSignals
+ .GroupBy(s => s.Identifier)
+ .Select(g => g.First())
+ .OrderBy(s => s.Date)
+ .ToList();
}
}
\ No newline at end of file
diff --git a/src/Managing.Web3Proxy/src/generated/ManagingApiTypes.ts b/src/Managing.Web3Proxy/src/generated/ManagingApiTypes.ts
index 6985348b..d269e8f3 100644
--- a/src/Managing.Web3Proxy/src/generated/ManagingApiTypes.ts
+++ b/src/Managing.Web3Proxy/src/generated/ManagingApiTypes.ts
@@ -1469,6 +1469,19 @@ export interface IndicatorRequestDto {
requesterName: string;
}
+export interface RefineIndicatorsResponse {
+ indicatorsValues?: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; } | null;
+ signals?: LightSignal[] | null;
+}
+
+export interface RefineIndicatorsRequest {
+ ticker: Ticker;
+ timeframe: Timeframe;
+ startDate: Date;
+ endDate: Date;
+ indicators: IndicatorRequest[];
+}
+
export interface LoginRequest {
name: string;
address: string;
diff --git a/src/Managing.WebApp/src/generated/ManagingApi.ts b/src/Managing.WebApp/src/generated/ManagingApi.ts
index 0db7d052..ed92fcdc 100644
--- a/src/Managing.WebApp/src/generated/ManagingApi.ts
+++ b/src/Managing.WebApp/src/generated/ManagingApi.ts
@@ -4137,6 +4137,45 @@ export class TradingClient extends AuthorizedApiBase {
}
return Promise.resolve(null as any);
}
+
+ trading_RefineIndicators(request: RefineIndicatorsRequest): Promise {
+ let url_ = this.baseUrl + "/Trading/RefineIndicators";
+ url_ = url_.replace(/[?&]$/, "");
+
+ const content_ = JSON.stringify(request);
+
+ let options_: RequestInit = {
+ body: content_,
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ "Accept": "application/json"
+ }
+ };
+
+ return this.transformOptions(options_).then(transformedOptions_ => {
+ return this.http.fetch(url_, transformedOptions_);
+ }).then((_response: Response) => {
+ return this.processTrading_RefineIndicators(_response);
+ });
+ }
+
+ protected processTrading_RefineIndicators(response: Response): Promise {
+ const status = response.status;
+ let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
+ if (status === 200) {
+ return response.text().then((_responseText) => {
+ let result200: any = null;
+ result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as RefineIndicatorsResponse;
+ return result200;
+ });
+ } else if (status !== 200 && status !== 204) {
+ return response.text().then((_responseText) => {
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
+ });
+ }
+ return Promise.resolve(null as any);
+ }
}
export class UserClient extends AuthorizedApiBase {
@@ -5972,6 +6011,19 @@ export interface IndicatorRequestDto {
requesterName: string;
}
+export interface RefineIndicatorsResponse {
+ indicatorsValues?: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; } | null;
+ signals?: LightSignal[] | null;
+}
+
+export interface RefineIndicatorsRequest {
+ ticker: Ticker;
+ timeframe: Timeframe;
+ startDate: Date;
+ endDate: Date;
+ indicators: IndicatorRequest[];
+}
+
export interface LoginRequest {
name: string;
address: string;
diff --git a/src/Managing.WebApp/src/generated/ManagingApiTypes.ts b/src/Managing.WebApp/src/generated/ManagingApiTypes.ts
index 6985348b..d269e8f3 100644
--- a/src/Managing.WebApp/src/generated/ManagingApiTypes.ts
+++ b/src/Managing.WebApp/src/generated/ManagingApiTypes.ts
@@ -1469,6 +1469,19 @@ export interface IndicatorRequestDto {
requesterName: string;
}
+export interface RefineIndicatorsResponse {
+ indicatorsValues?: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; } | null;
+ signals?: LightSignal[] | null;
+}
+
+export interface RefineIndicatorsRequest {
+ ticker: Ticker;
+ timeframe: Timeframe;
+ startDate: Date;
+ endDate: Date;
+ indicators: IndicatorRequest[];
+}
+
export interface LoginRequest {
name: string;
address: string;