Login Page - Create Account

Support Board


Date/Time: Thu, 15 Jan 2026 01:42:06 +0000



Post From: Displaying Custom Bars on the Chart

[2025-12-07 12:10:05]
User431178 - Posts: 833
I used the code on the website to create a Custom Bars study, which compiles fine but when I apply it to a 1-tick chart, it doesnt display anything. here is the code

It's clearly not a verbatim copy of the published code, your AI added some random unnecessary stuff to your code.

This is the main problem, custom chart study is always hidden, setting it to display as main graph = blank chart.

sc.DisplayAsMainPriceGraph = 1; // This is crucial

Code below is working as expected.

#include "sierrachart.h"
SCDLLName("Working Custom Range Bars")

// Forward declarations for our functions
SCSFExport BuildCustomRangeBars(SCCustomChartBarInterfaceRef ChartBarInterface);

int GetRangeBarDirection(SCCustomChartBarInterfaceRef ChartBarInterface, int BarIndex);



// This is the main study function. It only runs once to set up the study.
// CORRECTED a typo here: SCStudyFocus -> SCStudyInterfaceRef
SCSFExport scsf_WorkingCustomRangeBars(SCStudyInterfaceRef sc)

{

if (sc.SetDefaults)
{

// --- Essential Settings for a Custom Price Graph ---

sc.GraphName = "Working Custom Range Bars";

sc.StudyDescription = "A working implementation of Sierra Chart's custom range bar example.";

sc.UsesCustomChartBarFunction = 1;
sc.fp_ACSCustomChartBarFunction = BuildCustomRangeBars;
sc.AutoLoop = 0; // The custom bar function handles the looping

// --- Input Setting ---

sc.Input[0].Name = "Range Per Bar in Ticks";
sc.Input[0].SetInt(10);
sc.Input[0].SetIntLimits(1, INT_MAX);

return;

}

int& r_ChartDataReloadedFlag = sc.GetPersistentInt(CUSTOM_CHART_BAR_RELOAD_FLAG_KEY);

if (r_ChartDataReloadedFlag == 0)
{
sc.FlagToReloadChartData = true;
r_ChartDataReloadedFlag = 1;
}

// --- Logic to automatically reload the chart if the range input changes ---

const int RangePerBar = sc.Input[0].GetInt();

int& r_PriorRangePerBar = sc.GetPersistentInt(1);

if (r_PriorRangePerBar != 0 && r_PriorRangePerBar != RangePerBar)
{
sc.FlagToReloadChartData = true;
}

r_PriorRangePerBar = RangePerBar;



if (sc.IsFullRecalculation)
{
sc.GraphName.Format("Custom Range Bar = %d", RangePerBar);
}

}



// This function is called by Sierra Chart for every tick of data to build the bars
SCSFExport BuildCustomRangeBars(SCCustomChartBarInterfaceRef ChartBarInterface)
{
ChartBarInterface.StartNewBarFlag = 0; // Default to not creating a new bar

const float NeededRangeAsFloat = ChartBarInterface.GetInput(0).GetInt() * ChartBarInterface.TickSize;
// Phase 1: Check if the current tick's price movement completes the current bar

if (ChartBarInterface.IsDeterminingIfShouldStartNewBar)
{
int Direction = GetRangeBarDirection(ChartBarInterface, ChartBarInterface.CurrentBarIndex);
float BarHigh = ChartBarInterface.GetChartBarValue(SC_HIGH, ChartBarInterface.CurrentBarIndex);
float BarLow = ChartBarInterface.GetChartBarValue(SC_LOW, ChartBarInterface.CurrentBarIndex);

if (Direction == 1) // Bar is moving up
{
BarHigh = max(BarHigh, ChartBarInterface.NewFileRecord.GetHigh());

if ((BarHigh - BarLow) >= NeededRangeAsFloat)
ChartBarInterface.StartNewBarFlag = 1;
}

else // Bar is moving down
{
BarLow = min(BarLow, ChartBarInterface.NewFileRecord.GetLow());

if ((BarHigh - BarLow) >= NeededRangeAsFloat)
ChartBarInterface.StartNewBarFlag = 1;
}
}
// Phase 2: After a new bar has been created, finalize the previous bar
else if (ChartBarInterface.IsFinalProcessingAfterNewOrCurrentBar)
{
if (ChartBarInterface.IsNewChartBar && ChartBarInterface.CurrentBarIndex > 0)
{
int PreviousBarIndex = ChartBarInterface.CurrentBarIndex - 1;
int Direction = GetRangeBarDirection(ChartBarInterface, PreviousBarIndex);

if (Direction == 1) // Finalize an up bar
{
// Set the Close equal to the High
ChartBarInterface.GetChartBarValue(SC_LAST, PreviousBarIndex) = ChartBarInterface.GetChartBarValue(SC_HIGH, PreviousBarIndex);
}
else // Finalize a down bar
{
// Set the Close equal to the Low
ChartBarInterface.GetChartBarValue(SC_LAST, PreviousBarIndex) = ChartBarInterface.GetChartBarValue(SC_LOW, PreviousBarIndex);
}
}
}
}

// Helper function to determine the direction of the current range bar
int GetRangeBarDirection(SCCustomChartBarInterfaceRef ChartBarInterface, int BarIndex)
{
for (int i = 0; i < 10 && BarIndex - i >= 0; ++i)
{
int CurrentIndex = BarIndex - i;
float& BarOpen = ChartBarInterface.GetChartBarValue(SC_OPEN, CurrentIndex);
float& BarLast = ChartBarInterface.GetChartBarValue(SC_LAST, CurrentIndex);

if (BarLast < BarOpen) return -1; // Down
if (BarLast > BarOpen) return 1; // Up

if (CurrentIndex > 0)
{
float& PriorBarLast = ChartBarInterface.GetChartBarValue(SC_LAST, CurrentIndex - 1);

if (BarLast < PriorBarLast) return -1; // Down
if (BarLast > PriorBarLast) return 1; // Up
}
}

return 1; // Default to up if undetermined
}