Login Page - Create Account

Support Board


Date/Time: Tue, 26 Nov 2024 01:53:13 +0000



Post From: sc.EarliestUpdateSubgraphDataArrayIndex seems broken with Study/Price Overlay

[2024-01-19 22:11:14]
User719512 - Posts: 264
FYI Sierra Chart Engineering and others interested parties,

I have found a workaround/solution that appears to work, at least for the test cases I need and a few charts I tested against.
Basically, from the source chart (chart#1), call RecalculateChart, and maintain a persistent variable to ignore the recalculation when raised from itself before proceeding normally.
This does require using manual looping (which is really the best way to write a study anyway).
Also there is logic for a "full recalculation" where the study should clear/reset any state/subgraphs/pointers/etc when the update index is 0.
The sample code below has these patterns, and for your own studies, care and understanding need to be taken to ensure correct behavior.

This pattern should work until such time as Sierra Engineering fixes how sc.EarliestUpdateSubgraphDataArrayIndex is managed across all charts.


SCSFExport scsf_123_RedrawWithOverlay(SCStudyInterfaceRef sc)
{
  SCString msg;
  int& r_RecalculateFlag = sc.GetPersistentIntFast(5);

  if (sc.SetDefaults)
  {
    sc.GraphName = "123_RedrawWithOverlay";
    sc.AutoLoop = 0; // DO NOT USE AutoLoop, manual only
    sc.DrawZeros = 0;
    sc.UpdateAlways = 1;

    sc.Subgraph[0].Name = "Value";
    sc.Subgraph[0].DrawStyle = DRAWSTYLE_LINE;
    sc.Subgraph[0].PrimaryColor = RGB(0, 255, 0);

    r_RecalculateFlag = 0;

    return;
  }

  // manual looping index so we can override sc.UpdateStartIndex when needed
  int scUpdateStartIndex;
  scUpdateStartIndex = sc.UpdateStartIndex;

  if (r_RecalculateFlag == 1)
  {
    // ensure we are being called with IsFullRecalculation and not just on a timer/event
    if (sc.IsFullRecalculation)
    {
      r_RecalculateFlag = 0;
    }
    return;
  }

  if (scUpdateStartIndex == 0) {
    // clear all SGs so Recalculate works properly
    for (int i = 0; i < SC_SUBGRAPHS_AVAILABLE; i++) {
      for (int barIndex = 0; barIndex < sc.ArraySize; barIndex++)
      {
        sc.Subgraph[i][barIndex] = 0;
      }
    }
  }

  bool shouldRecalculateChart = false;
  int bucketSize = 10; // even number is best

  for (int barIndex = scUpdateStartIndex; barIndex < sc.ArraySize; barIndex++)
  {
    if (sc.GetBarHasClosedStatus(barIndex) == BHCS_BAR_HAS_NOT_CLOSED)
    {
      return;
    }

    if ((barIndex % bucketSize) < bucketSize / 2)
    {
      if ((barIndex % bucketSize) == 0)
      {
        // show all the SG data back to index 0
        // by setting value to 0
        for (int barIndex = 0; barIndex < sc.ArraySize; barIndex++)
        {
          sc.Subgraph[0][barIndex] = sc.Low[barIndex];
        }
        shouldRecalculateChart = true;
        msg.Format("%d: Show all", barIndex);
        sc.AddMessageToLog(msg, 1);

        if (!sc.IsFullRecalculation)
        {
          sc.EarliestUpdateSubgraphDataArrayIndex = 0;
        }
      }
      else
      {
        // just update this index
        sc.Subgraph[0][barIndex] = sc.Low[barIndex];
      }
    }
    else
    if ((barIndex % bucketSize) == bucketSize / 2)
    {
      // hide all the SG data back to index 0
      // by setting value to 0
      for (int barIndex = 0; barIndex < sc.ArraySize; barIndex++)
      {
        sc.Subgraph[0][barIndex] = 0;
      }
      shouldRecalculateChart = true;

      msg.Format("%d: Hide all", barIndex);
      sc.AddMessageToLog(msg, 1);

      if (!sc.IsFullRecalculation)
      {
        sc.EarliestUpdateSubgraphDataArrayIndex = 0;
      }
    }
  }

  if (shouldRecalculateChart)
  {
    sc.RecalculateChart(sc.ChartNumber);
    r_RecalculateFlag = 1;
  }
}