Support Board
Date/Time: Sun, 30 Nov 2025 09:19:36 +0000
Displaying Custom Bars on the Chart
View Count: 8
| [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:
