Login Page - Create Account

Support Board


Date/Time: Thu, 15 Jan 2026 00:09:29 +0000



[Programming Help] - Displaying Custom Bars on the Chart

View Count: 237

[2025-11-30 05:54:48]
User572973 - Posts: 4
I'm trying to display Custom Range bars on the chart. 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:


#include "sierrachart.h"

SCDLLName("Working Custom Range Bars")

// Forward declarations for our functions
void 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.IsCustomChart = 1;
sc.DisplayAsMainPriceGraph = 1; // This is crucial
sc.GraphRegion = 0;
sc.GraphDrawType = GDT_OHLCBAR; // Draw as candlesticks/bars
sc.StandardChartHeader = 1;
sc.DrawZeros = 0;

// --- Link our custom function to Sierra Chart ---
sc.UsesCustomChartBarFunction = 1;
sc.fp_ACSCustomChartBarFunction = BuildCustomRangeBars;

// --- KEY FIX: Define ALL standard price subgraphs ---
// Even if not displayed, the drawing engine needs these arrays to exist.
sc.Subgraph[SC_OPEN].Name = "Open";
sc.Subgraph[SC_OPEN].DrawStyle = DRAWSTYLE_IGNORE;
sc.Subgraph[SC_HIGH].Name = "High";
sc.Subgraph[SC_HIGH].DrawStyle = DRAWSTYLE_IGNORE;
sc.Subgraph[SC_LOW].Name = "Low";
sc.Subgraph[SC_LOW].DrawStyle = DRAWSTYLE_IGNORE;
sc.Subgraph[SC_LAST].Name = "Last";
sc.Subgraph[SC_LAST].DrawStyle = DRAWSTYLE_IGNORE;
sc.Subgraph[SC_VOLUME].Name = "Volume";
sc.Subgraph[SC_VOLUME].DrawStyle = DRAWSTYLE_IGNORE;

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

sc.AutoLoop = 0; // The custom bar function handles the looping

return;
}

// --- 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
void 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
}

[2025-12-06 17:32:32]
User572973 - Posts: 4
any pointers on this please ? thx
[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
}

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

Login

Login Page - Create Account