Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 5, 2025

All overlay indicators (SMA, DEMA, ADR, etc.) returned empty plot arrays while non-overlay indicators worked correctly. The ta-series wrapper functions were accessing (source as any).data instead of source.bars, causing Series.fromArray() to receive undefined and produce empty arrays.

Changes

  • packages/oakscriptjs/src/ta-series.ts: Fixed 22 occurrences of .data.bars across sma, ema, wma, rma, rsi, macd, stdev, variance, crossover, crossunder, cross, and other functions

  • example/src/: Added detailed value logging to chart.ts and indicator-ui.ts for debugging plot data

  • tests/: Added integration tests for ta-series functions and overlay/non-overlay indicators

Example

// Before (broken)
export function sma(source: Series, length: number): Series {
  const bars = (source as any).data as Bar[];  // undefined
  const result = taCore.sma(sourceValues, length);
  return Series.fromArray(bars, result);  // Returns empty array
}

// After (fixed)
export function sma(source: Series, length: number): Series {
  const bars = source.bars as Bar[];  // Correct property
  const result = taCore.sma(sourceValues, length);
  return Series.fromArray(bars, result);  // Returns correct data
}
Original prompt

Fix overlay indicators returning empty plot data

Problem Analysis

Based on the debug logs, I've identified the root cause:

Key Findings from Logs:

  1. SMA plot0 is empty from the indicator itself:

    [IndicatorUI] recalculate - result.plots: 
    Object { plot0: [], plot1: (13570) […], plot2: (13570) […], plot3: (13570) […] }
    

    The main SMA plot (plot0) returns an empty array [], while smoothing plots have data.

  2. All overlay indicators have this issue:

    • SMA: plot0: []
    • DEMA: plot0: []
    • ADR: plot0: []
  3. Non-overlay indicators work correctly:

    • Momentum: plot0: (13570) [...] with filtered data length: 13560
    • BOP: plot0: (13570) [...] with filtered data length: 13560
    • ROC: plot0: (13570) [...] with filtered data length: 13561
  4. Even when plot1/plot2/plot3 have 13570 items, filtered length is 0:

    [ChartManager] setIndicatorData - data length: 13570
    [ChartManager] setIndicatorData - filtered data length: 0
    

    This means all 13570 values are being filtered out as NaN/null.

Root Cause

The issue is in the transpiled indicator code. Looking at indicators/sma/sma.ts:

return {
  metadata: { title: "Moving Average Simple", shorttitle: "SMA", overlay: true },
  plots: { 'plot0': out.toArray().map((v: number | undefined, i: number) => ({ time: bars[i]!.time, value: v ?? NaN })), ...

The out.toArray() is returning an empty array. This could be because:

  1. The ta.sma() function is not returning data correctly
  2. The Series chain is not evaluating properly
  3. There's an issue with how the transpiled code creates Series objects

Required Fix

1. Add detailed value logging to see actual data

In example/src/chart.ts, log the first few actual values:

console.log('[ChartManager] setIndicatorData - first 3 values:', data.slice(0, 3).map(d => ({ time: d.time, value: d.value, valueType: typeof d.value })));

2. Add logging in indicator-ui.ts for first calculation result values

if (result?.plots) {
  for (const [plotId, plotData] of Object.entries(result.plots)) {
    if (Array.isArray(plotData) && plotData.length > 0) {
      console.log(`[IndicatorUI] ${plotId} first 3 values:`, plotData.slice(0, 3));
    }
  }
}

3. Investigate the actual indicator output format

The issue might be that the indicator's plots object format doesn't match what indicator-ui.ts expects. The indicators might be using a different structure.

Check if the indicators are using:

  • result.plots[plotDef.id] - array of {time, value} objects
  • Or some other format that needs transformation

4. Check the time format

The bars have time as Unix timestamp (seconds). Verify the indicator output also uses the same format and it's compatible with LightweightCharts.

Files to Modify

  1. example/src/chart.ts - Add more detailed value logging
  2. example/src/indicator-ui.ts - Add logging for actual plot values

Alternative Root Cause Investigation

If the ta.sma() is returning values correctly but they're being mapped to NaN, check:

  1. Is bars[i]!.time actually a valid number for all indices?
  2. Is the spread operator or mapping creating issues?
  3. Are the overlay indicator calculations using a different code path that has a bug?

Debug Output Needed

After adding logs, we need to see:

  1. What are the actual time and value in the first few data points?
  2. Are they numbers, strings, undefined, or NaN?
  3. Is the time format compatible with what the chart expects?

This pull request was created as a result of the following prompt from Copilot chat.

Fix overlay indicators returning empty plot data

Problem Analysis

Based on the debug logs, I've identified the root cause:

Key Findings from Logs:

  1. SMA plot0 is empty from the indicator itself:

    [IndicatorUI] recalculate - result.plots: 
    Object { plot0: [], plot1: (13570) […], plot2: (13570) […], plot3: (13570) […] }
    

    The main SMA plot (plot0) returns an empty array [], while smoothing plots have data.

  2. All overlay indicators have this issue:

    • SMA: plot0: []
    • DEMA: plot0: []
    • ADR: plot0: []
  3. Non-overlay indicators work correctly:

    • Momentum: plot0: (13570) [...] with filtered data length: 13560
    • BOP: plot0: (13570) [...] with filtered data length: 13560
    • ROC: plot0: (13570) [...] with filtered data length: 13561
  4. Even when plot1/plot2/plot3 have 13570 items, filtered length is 0:

    [ChartManager] setIndicatorData - data length: 13570
    [ChartManager] setIndicatorData - filtered data length: 0
    

    This means all 13570 values are being filtered out as NaN/null.

Root Cause

The issue is in the transpiled indicator code. Looking at indicators/sma/sma.ts:

return {
  metadata: { title: "Moving Average Simple", shorttitle: "SMA", overlay: true },
  plots: { 'plot0': out.toArray().map((v: number | undefined, i: number) => ({ time: bars[i]!.time, value: v ?? NaN })), ...

The out.toArray() is returning an empty array. This could be because:

  1. The ta.sma() function is not returning data correctly
  2. The Series chain is not evaluating properly
  3. There's an issue with how the transpiled code creates Series objects

Required Fix

1. Add detailed value logging to see actual data

In example/src/chart.ts, log the first few actual values:

console.log('[ChartManager] setIndicatorData - first 3 values:', data.slice(0, 3).map(d => ({ time: d.time, value: d.value, valueType: typeof d.value })));

2. Add logging in indicator-ui.ts for first calculation result values

if (result?.plots) {
  for (const [plotId, plotData] of Object.entries(result.plots)) {
    if (Array.isArray(plotData) && plotData.length > 0) {
      console.log(`[IndicatorUI] ${plotId} first 3 values:`, plotData.slice(0, 3));
    }
  }
}

3. Investigate the actual indicator output format

The issue might be that the indicator's plots object format doesn't match what indicator-ui.ts expects. The indicators might be using a different structure.

Check if the indicators are using:

  • result.plots[plotDef.id] - array of {time, value} objects
  • Or some other format that needs transformation

4. Check the time format

The bars have time as Unix timestamp (seconds). Verify the indicator output also uses the same format and it's compatible with LightweightCharts.

Files to Modify

  1. example/src/chart.ts - Add more detailed value logging
  2. example/src/indicator-ui.ts - Add logging for actual plot values

Alternative Root Cause Investigation

If the ta.sma() is returning values correctly but they're being mapped to NaN, check:

  1. Is bars[i]!.time actually a valid number for all indices?
  2. Is the spread operator or mapping creating issues?
  3. Are the overlay indicator calculations using a different code path that has a bug?

Debug Output Needed

After adding logs, we need to see:

  1. What are the actual time and value in the first few data points?
  2. Are they numbers, strings, undefined, or NaN?
  3. Is the time format compatible with what the chart expects?

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits December 5, 2025 10:39
…to .bars

Co-authored-by: deepentropy <8287111+deepentropy@users.noreply.github.com>
Co-authored-by: deepentropy <8287111+deepentropy@users.noreply.github.com>
Co-authored-by: deepentropy <8287111+deepentropy@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix overlay indicators returning empty plot data Fix ta-series functions accessing non-existent .data property Dec 5, 2025
Copilot AI requested a review from deepentropy December 5, 2025 10:49
@deepentropy deepentropy marked this pull request as ready for review December 5, 2025 10:50
Copilot AI review requested due to automatic review settings December 5, 2025 10:50
@deepentropy deepentropy merged commit 8651f56 into main Dec 5, 2025
2 of 4 checks passed
@deepentropy deepentropy deleted the copilot/fix-overlay-indicators-plot-data branch December 5, 2025 10:51
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a critical bug where all overlay indicators (SMA, DEMA, ADR, etc.) returned empty plot arrays due to accessing a non-existent .data property instead of the correct .bars property on Series objects. The fix ensures that ta-series wrapper functions properly access the underlying bar data, allowing Series.fromArray() to receive valid data instead of undefined.

Key changes:

  • Fixed 22 ta-series wrapper functions to use source.bars instead of (source as any).data
  • Added integration tests to verify the fix works correctly for both overlay and non-overlay indicators
  • Enhanced debug logging in example application to track plot data values

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/oakscriptjs/src/ta-series.ts Fixed 22 occurrences where .data was incorrectly accessed instead of .bars on Series objects across all wrapper functions (sma, ema, wma, rma, rsi, macd, bb, stdev, crossover, crossunder, cross, change, mom, roc, highest, lowest, rising, falling, cum, vwap, vwma, linreg)
packages/oakscriptjs/tests/ta/ta-series-integration.test.ts Added integration tests for ta.sma and multiple ta functions to verify .bars fix returns correct array lengths with non-NaN data
packages/oakscriptjs/tests/indicators/overlay-indicators.test.ts Added tests for overlay indicators (SMA, DEMA) and non-overlay indicators (Momentum, BOP) to verify plot0 returns data with correct structure
example/src/chart.ts Enhanced debug logging to show first 3 values with time, value, and valueType for better troubleshooting
example/src/indicator-ui.ts Added debug logging to display first 3 values of each plot for debugging plot data issues
Comments suppressed due to low confidence (1)

example/src/chart.ts:177

  • Unused variable id.
    for (const [id, series] of this.indicatorSeries) {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants