Login Page - Create Account

Support Board


Date/Time: Wed, 28 Jan 2026 17:55:25 +0000



[Programming Help] - how to calculate and plot over arrays on different timeframes in ACSIL?

View Count: 309

[2025-12-12 06:10:55]
User463324 - Posts: 5
Hi,

I have a base chart on 15 seconds timeframe, and I'm adding a custom study/indicator that calculates certain metrics over 1 min timeframe and plots them on my 15 second chart. My study adds automatically 1 min subchart using and OpenChartOrGetChartReference and I try to use subarrays using GetStudyExtraArrayFromChartUsingID for my custom calculations but indexing and aggregations over these sub arrays are not working right (summations are not valid and overall looping over these subarrays is returning strange results). source is below. What am I doing wrong?


SCSFExport scsf_SimulationBackgroundColor(SCStudyInterfaceRef sc)
{
SCSubgraphRef testSubgraph = sc.Subgraph[0];

SCInputRef Input_Length = sc.Input[0];

if (sc.SetDefaults)
{
sc.GraphName = "MyTest";
sc.StudyDescription = "MyTest";

Input_Length.Name = "Test Length";
Input_Length.SetInt(100);

sc.DisplayStudyInputValues = false;
sc.AutoLoop = true;
sc.DrawStudyUnderneathMainPriceGraph = 1;
}

const int P_ONE_MIN_CHART = 1;

int& oneMinChartNumber = sc.GetPersistentInt(P_ONE_MIN_CHART);
if (sc.IsFullRecalculation || sc.Index == 0)
{
s_ACSOpenChartParameters oneMinParams;
oneMinParams.PriorChartNumber = oneMinChartNumber;
oneMinParams.DaysToLoad = 0;
oneMinParams.ChartDataType = INTRADAY_DATA;
oneMinParams.Symbol = sc.GetRealTimeSymbol();
oneMinParams.IntradayBarPeriodType = IBPT_DAYS_MINS_SECS;
oneMinParams.IntradayBarPeriodLength = 1 * SECONDS_PER_MINUTE;
oneMinParams.HideNewChart = true;
oneMinParams.LoadWeekendData = true;
oneMinParams.UseEveningSession = true;
oneMinParams.UpdatePriorChartNumberParametersToMatch = true;
oneMinChartNumber = sc.OpenChartOrGetChartReference(oneMinParams);
sc.SetPersistentInt(P_ONE_MIN_CHART, oneMinChartNumber);
}

if (oneMinChartNumber != 0)
{
SCDateTimeArray oneMinDateTimes;
sc.GetChartDateTimeArray(oneMinChartNumber, oneMinDateTimes);

SCGraphData oneMinData;
sc.GetChartBaseData(oneMinChartNumber, oneMinData);
int dataIndex = oneMinDateTimes.GetArraySize() - 1;

SCFloatArray tpv;
sc.GetStudyExtraArrayFromChartUsingID(oneMinChartNumber, Input_Length.GetStudyID(), 0, 0, tpv);
SCFloatArray tpvSum;
sc.GetStudyExtraArrayFromChartUsingID(oneMinChartNumber, Input_Length.GetStudyID(), 0, 1, tpvSum);

float atp = (oneMinData[SC_LAST][dataIndex] + oneMinData[SC_HIGH][dataIndex] + oneMinData[SC_LOW][dataIndex]) / 3;
float tpvVal = atp * oneMinData[SC_VOLUME][dataIndex];
tpv[dataIndex] = tpvVal;
sc.Summation(tpv, tpvSum, Input_Length.GetInt());
SCString FormattedMessage;
sc.AddMessageToLog(FormattedMessage.Format("sc.index=%i dataIndex=%i oneMinDataLen=%i tpvLen=%i", sc.Index, dataIndex, oneMinData.GetArraySize(), tpv.GetArraySize()), 0);
testSubgraph[sc.Index] = tpvSum[dataIndex];
}
}

[2025-12-12 08:19:01]
User431178 - Posts: 838
This is not the right approach as it will always give you the end of the other chart.
int dataIndex = oneMinDateTimes.GetArraySize() - 1;

There is a whole docs section about it.
Referencing Other Time Frames and Symbols When Using the ACSIL

ACSIL Interface Members - Functions: sc.GetContainingIndexForSCDateTime()
ACSIL Interface Members - Functions: sc.GetNearestMatchForSCDateTime()
[2025-12-12 13:43:54]
User463324 - Posts: 5
Thanks, I saw those docs. Iteration over oneMinDateTimes works just fine with the approach above and also fetching various candle metrics from oneMinData by those datetime indexes also works.
What doesn't work is indexing over extra arrays fetched with GetStudyExtraArrayFromChartUsingID, using Summation and other math functions over them.

I don't want to use sc.GetContainingIndexForSCDateTime() and sc.GetNearestMatchForSCDateTime() bc in reality my time logic is more complex and requires my own iteration and keeping track of indexes, but this is not the problem either way - the issue is with extra arrays, that I thought would indexeable the same way as chart from which they are fetched.
Any other ways to do this? Do I need to roll my own SCFloatArray?
[2025-12-12 14:58:49]
User431178 - Posts: 838
Iteration over oneMinDateTimes works just fine with the approach above and also fetching various candle metrics from oneMinData by those datetime indexes also works.
Sure, it just means that all bars would have the same value set during recalculation.

the issue is with extra arrays, that I thought would indexeable the same way as chart from which they are fetched.
They are.


Input_Length.Name = "Test Length";
Input_Length.SetInt(100);


sc.GetStudyExtraArrayFromChartUsingID(oneMinChartNumber, Input_Length.GetStudyID(), 0, 0, tpv);

This won’t work correctly because SetInt writes to the first 4 bytes (offset 0–3) of the union inside sc.Input, while GetStudyID reads from bytes 4–7, which were never written by SetInt and therefore contain unrelated or undefined data.



tpv[dataIndex] = tpvVal;
sc.Summation(tpv, tpvSum, Input_Length.GetInt());

What are you trying to do here?

You are getting from the other chart then writing over it in your local float array.
The values you set won't persist between function calls.
When you call sc.Summation without an index value, it uses sc.Index so that won't be referring to the correct (one minute) indexes in tpv or tpvSum anyway.

Is the code you posted representative of what you are trying to do, or it is edited for posting and not necessariliy correct?
Date Time Of Last Edit: 2025-12-12 15:00:02
[2025-12-12 15:19:02]
User463324 - Posts: 5
> Sure, it just means that all bars would have the same value set during recalculation.

They do not - in oneMindData subgraphs - I tested this. sc.AutoLoop = true; seems to makes it all work.

>tpv[dataIndex] = tpvVal;
>sc.Summation(tpv, tpvSum, Input_Length.GetInt());
>What are you trying to do here?

I'd like calculate a rolling sum of one minute average true price data multiplied by one minute volume, of length 100, which then I'm plotting on my primary 15 second chart. My actual indicators are very different but this shows what I'm trying to do.
[2025-12-12 16:19:37]
User431178 - Posts: 838
They do not - in oneMindData subgraphs - I tested this. sc.AutoLoop = true; seems to makes it all work.

This is from the message log, generated using your code exactly as posted.


2025-12-12 09:34:33.864 | Chart: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=0 dataIndex=987 oneMinDataLen=60 tpvLen=0
2025-12-12 09:34:33.864 | Chart: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=1 dataIndex=987 oneMinDataLen=60 tpvLen=0
2025-12-12 09:34:33.864 | Chart: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=2 dataIndex=987 oneMinDataLen=60 tpvLen=0
2025-12-12 09:34:33.864 | Chart: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=3 dataIndex=987 oneMinDataLen=60 tpvLen=0
2025-12-12 09:34:33.864 | Chart: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=4 dataIndex=987 oneMinDataLen=60 tpvLen=0
....
2025-12-12 09:34:33.890 | Chart: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=3866 dataIndex=987 oneMinDataLen=60 tpvLen=0
2025-12-12 09:34:33.890 | Chart: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=3867 dataIndex=987 oneMinDataLen=60 tpvLen=0
2025-12-12 09:34:33.890 | Chart: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=3868 dataIndex=987 oneMinDataLen=60 tpvLen=0
2025-12-12 09:34:33.890 | Chart: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=3869 dataIndex=987 oneMinDataLen=60 tpvLen=0
2025-12-12 09:34:33.890 | Chart: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=3870 dataIndex=987 oneMinDataLen=60 tpvLen=0

Notice that dataIndex is 987 from start to end.
Which means that this code will have the exact same value for every bar in the chart - is that what you want?

float atp = (oneMinData[SC_LAST][dataIndex] + oneMinData[SC_HIGH][dataIndex] + oneMinData[SC_LOW][dataIndex]) / 3;


I'd like calculate a rolling sum of one minute average true price data multiplied by one minute volume, of length 100, which then I'm plotting on my primary 15 second chart. My actual indicators are very different but this shows what I'm trying to do.

So you don't actually have any study in the 1-min chart, you literally want the 1-min graph data?
If that is the case, what are you expecting from this, there is no study to reference and no "extra arrays" to get?


SCFloatArray tpv;
sc.GetStudyExtraArrayFromChartUsingID(oneMinChartNumber, Input_Length.GetStudyID(), 0, 0, tpv);

SCFloatArray tpvSum;
sc.GetStudyExtraArrayFromChartUsingID(oneMinChartNumber, Input_Length.GetStudyID(), 0, 1, tpvSum);

[2025-12-12 16:27:48]
User431178 - Posts: 838
I probably wouldn't do it like this, but it does calculate a rolling sum of one minute average true price data multiplied by one minute volume.


SCSFExport scsf_SimulationBackgroundColor(SCStudyInterfaceRef sc)
{
SCSubgraphRef testSubgraph = sc.Subgraph[0];
SCInputRef Input_Length = sc.Input[0];

if (sc.SetDefaults)
{
sc.GraphName = "MyTest";
sc.StudyDescription = "MyTest";

Input_Length.Name = "Test Length";
Input_Length.SetInt(100);

  testSubgraph.Name = "Test Subgraph";
  testSubgraph.DrawStyle = DRAWSTYLE_LINE;
  testSubgraph.PrimaryColor = RGB(255, 0, 0);
  testSubgraph.LineWidth = 2;


sc.DisplayStudyInputValues = false;
sc.AutoLoop = true;
sc.DrawStudyUnderneathMainPriceGraph = 1;

}

const int P_ONE_MIN_CHART = 1;

int& oneMinChartNumber = sc.GetPersistentInt(P_ONE_MIN_CHART);

if (sc.IsFullRecalculation || sc.Index == 0)
{
s_ACSOpenChartParameters oneMinParams;

oneMinParams.PriorChartNumber = oneMinChartNumber;
oneMinParams.DaysToLoad = 0;
oneMinParams.ChartDataType = INTRADAY_DATA;
oneMinParams.Symbol = sc.GetRealTimeSymbol();
oneMinParams.IntradayBarPeriodType = IBPT_DAYS_MINS_SECS;
oneMinParams.IntradayBarPeriodLength = 1 * SECONDS_PER_MINUTE;
oneMinParams.HideNewChart = true;
oneMinParams.LoadWeekendData = true;
oneMinParams.UseEveningSession = true;
oneMinParams.UpdatePriorChartNumberParametersToMatch = true;
oneMinChartNumber = sc.OpenChartOrGetChartReference(oneMinParams);

sc.SetPersistentInt(P_ONE_MIN_CHART, oneMinChartNumber);
}

if (sc.Index < sc.ArraySize - 1
&& sc.IsFullRecalculation)
return;

if (oneMinChartNumber != 0)
{
SCGraphData oneMinData;
sc.GetChartBaseData(oneMinChartNumber, oneMinData);

if (oneMinData.GetArraySize() == 0)
return;

int dataIndex = oneMinData[SC_OPEN].GetArraySize() - 1;

auto tpvSum{ 0.0 };

for (auto offset = 0; offset < Input_Length.GetInt(); ++offset)
{
if (dataIndex - offset < 0)
break;

auto refIndex = dataIndex - offset;
auto tpvVal = static_cast<double>(oneMinData[SC_HLC][refIndex]) * static_cast<double>(oneMinData[SC_VOLUME][refIndex]);
tpvSum += tpvVal;
  }

SCString FormattedMessage;

sc.AddMessageToLog(FormattedMessage.Format("sc.index=%i dataIndex=%i oneMinDataLen=%i tpvSum=%.2f", sc.Index, dataIndex, oneMinData[0].GetArraySize(), tpvSum), 0);

testSubgraph[sc.Index] = static_cast<float>(tpvSum);
}
}

2025-12-12 10:23:57.182 | Chart: Replay 30X: ESZ25-CME[M] 15 Sec #1 | Study: MyTest | sc.index=3704 dataIndex=946 oneMinDataLen=947 tpvSum=868519156.64

That is my last comment / contribution on this.
Hope you get it working how you want.
Date Time Of Last Edit: 2025-12-12 16:29:56
[2025-12-12 17:17:53]
User463324 - Posts: 5
Thank you for your solution, it's very helpful. Correct, I don't have any secondary chart that has any studies - other than what's being opened automatically by this indicator code above with OpenChartOrGetChartReference.

I guess it's a request for sierrachart people then to enhance GetStudyExtraArrayFromChartUsingID so that it works properly even if there are no studies on the chart opened with OpenChartOrGetChartReference (or provide some other way to create series/arrays that are indexed based on the secondary chart).
[2025-12-12 18:51:34]
User431178 - Posts: 838
enhance GetStudyExtraArrayFromChartUsingID so that it works properly even if there are no studies on the chart
How do you get something that is not there, it does not make sense.


or provide some other way to create series/arrays that are indexed based on the secondary chart
You have the whole of c++ language at your fingertips.
I would use std::vector (and relevant algorithms) and keep the size synced with the chart that you are referencing, but that's just me.
[2025-12-12 19:41:33]
User463324 - Posts: 5
honestly, I don't really want sierra to even open any charts with OpenChartOrGetChartReference (visually anywhere) - it should just give me a pointer to a dataset for the the symbol and bars/timeframe that I open, and support deriving additional series from it and applying all the standard indicators/math functions over it as it's looping/fetching new data, similar to how other similar tools do it. I do like the power of c++ here, just some nicer convenience using standard sierrachart functions/api would be nice.

To post a message in this thread, you need to log in with your Sierra Chart account:

Login

Login Page - Create Account