Login Page - Create Account

Support Board


Date/Time: Sun, 30 Nov 2025 09:57:12 +0000



Displaying Custom Bars on the Chart

View Count: 9

[2025-11-30 05:54:48]
User572973 - Posts: 3
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
}

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

Login

Login Page - Create Account