Login Page - Create Account

Support Board


Date/Time: Sun, 15 Jun 2025 16:00:01 +0000



[Programming Help] - ACSIL study

View Count: 216

[2025-06-08 00:49:19]
User936417 - Posts: 16
Are there internal limitations in how Sierra Chart makes those drawings accessible to ACSIL studies—especially for manual DRAWING_LINE tools.I am trying to write a study that projects lines 12, 15, and 22 points beyond a newly drawn Line tool line. I have a successful build with subgraphs and all but the projected lines will not appear.
[2025-06-08 09:21:52]
User431178 - Posts: 711
Are there internal limitations in how Sierra Chart makes those drawings accessible to ACSIL studies—especially for manual DRAWING_LINE tools
No, you can access all of those.

I am trying to write a study that projects lines 12, 15, and 22 points beyond a newly drawn Line tool line. I have a successful build with subgraphs and all but the projected lines will not appear.
If you want help, you'll need to post the code.
[2025-06-08 23:57:51]
User936417 - Posts: 16
Here is the code:

#include "sierrachart.h"

SCDLLName("Line Tool Projections")

#ifndef DRAWING_LINE
#define DRAWING_LINE 8
#endif

SCSFExport scsf_LineToolProjections(SCStudyInterfaceRef sc)
{
SCInputRef Level1 = sc.Input[0];
SCInputRef Level2 = sc.Input[1];
SCInputRef Level3 = sc.Input[2];
SCInputRef ShowLevelValues = sc.Input[3];

// Subgraphs for projected level outputs
SCSubgraphRef Level1Up = sc.Subgraph[0];
SCSubgraphRef Level2Up = sc.Subgraph[1];
SCSubgraphRef Level3Up = sc.Subgraph[2];
SCSubgraphRef Level1Down = sc.Subgraph[3];
SCSubgraphRef Level2Down = sc.Subgraph[4];
SCSubgraphRef Level3Down = sc.Subgraph[5];

if (sc.SetDefaults)
{
sc.GraphName = "Line Tool Projections";
sc.AutoLoop = 0;

Level1.Name = "Projection Level 1 (points)";
Level1.SetInt(9);

Level2.Name = "Projection Level 2 (points)";
Level2.SetInt(13);

Level3.Name = "Projection Level 3 (points)";
Level3.SetInt(19);

ShowLevelValues.Name = "Show Level Value Labels";
ShowLevelValues.SetYesNo(1);

// Subgraph settings
Level1Up.Name = "Level 1 Up";
Level1Up.DrawStyle = DRAWSTYLE_LINE;
Level1Up.PrimaryColor = RGB(0, 255, 0);

Level2Up.Name = "Level 2 Up";
Level2Up.DrawStyle = DRAWSTYLE_LINE;
Level2Up.PrimaryColor = RGB(0, 200, 0);

Level3Up.Name = "Level 3 Up";
Level3Up.DrawStyle = DRAWSTYLE_LINE;
Level3Up.PrimaryColor = RGB(0, 150, 0);

Level1Down.Name = "Level 1 Down";
Level1Down.DrawStyle = DRAWSTYLE_LINE;
Level1Down.PrimaryColor = RGB(255, 0, 0);

Level2Down.Name = "Level 2 Down";
Level2Down.DrawStyle = DRAWSTYLE_LINE;
Level2Down.PrimaryColor = RGB(200, 0, 0);

Level3Down.Name = "Level 3 Down";
Level3Down.DrawStyle = DRAWSTYLE_LINE;
Level3Down.PrimaryColor = RGB(150, 0, 0);

return;
}

if (sc.UpdateStartIndex != sc.ArraySize - 1)
return;

const int ToolType = static_cast<int>(DRAWING_LINE);
const int DrawingCount = sc.GetACSDrawingsCount(sc.ChartNumber, ToolType);

if (DrawingCount == 0)
{
sc.AddMessageToLog("LineToolProjections: No line drawings found.", 0);
return;
}

for (int i = DrawingCount - 1; i >= 0; --i)
{
s_UseTool Tool;
if (!sc.GetACSDrawingByIndex(sc.ChartNumber, i, Tool, ToolType))
continue;

if (Tool.DrawingType != static_cast<DrawingTypeEnum>(DRAWING_LINE))
continue;

float High = max(Tool.BeginValue, Tool.EndValue);
float Low = min(Tool.BeginValue, Tool.EndValue);

float Level1Val = static_cast<float>(Level1.GetInt());
float Level2Val = static_cast<float>(Level2.GetInt());
float Level3Val = static_cast<float>(Level3.GetInt());

float Levels[6] = {
High + Level1Val,
High + Level2Val,
High + Level3Val,
Low - Level1Val,
Low - Level2Val,
Low - Level3Val
};

// Plot subgraph values
Level1Up[sc.Index] = Levels[0];
Level2Up[sc.Index] = Levels[1];
Level3Up[sc.Index] = Levels[2];
Level1Down[sc.Index] = Levels[3];
Level2Down[sc.Index] = Levels[4];
Level3Down[sc.Index] = Levels[5];

// Draw horizontal projected lines
for (int j = 0; j < 6; ++j)
{
s_UseTool LineTool;
LineTool.Clear();
LineTool.ChartNumber = sc.ChartNumber;
LineTool.DrawingType = static_cast<DrawingTypeEnum>(DRAWING_LINE);
LineTool.BeginValue = Levels[j];
LineTool.BeginDateTime = sc.BaseDateTimeIn[sc.ArraySize - 1].GetAsDouble();
LineTool.Color = RGB(0, 255, 0);
LineTool.AddMethod = UTAM_ADD_ALWAYS;

if (ShowLevelValues.GetYesNo())
{
char Label[32];
snprintf(Label, sizeof(Label), "%.2f", Levels[j]);
LineTool.Text = Label;
}

sc.UseTool(LineTool);
}

break; // Only process most recent line
}
}
[2025-06-09 12:33:33]
User431178 - Posts: 711
If you want to interact with user drawn elements, then you need to use the appropriate functions.

sc.GetUserDrawnDrawingsCount instead of sc.GetACSDrawingsCount
sc.GetUserDrawnChartDrawing instead of sc.GetACSDrawingByIndex

Using Drawing Tools From an Advanced Custom Study: sc.GetUserDrawnChartDrawing()
[2025-06-10 01:03:22]
User936417 - Posts: 16
thank you for your help. I am still not there. Build works but no lines are projected. I made the changes that you suggested above. i am getting the following in the message log: 2025-06-09 21:00:06.631 | Chart: ESM25_FUT_CME [CB][M] 5 Min #7 | Study: Line Tool Projections | LineToolProjections: No line drawings found. Here is the code with changes you suggested.


#include "sierrachart.h"

SCDLLName("Line Tool Projections")

#ifndef DRAWING_LINE
#define DRAWING_LINE 8
#endif

SCSFExport scsf_LineToolProjections(SCStudyInterfaceRef sc)
{
SCInputRef Level1 = sc.Input[0];
SCInputRef Level2 = sc.Input[1];
SCInputRef Level3 = sc.Input[2];
SCInputRef ShowLevelValues = sc.Input[3];

// Subgraphs for projected level outputs
SCSubgraphRef Level1Up = sc.Subgraph[0];
SCSubgraphRef Level2Up = sc.Subgraph[1];
SCSubgraphRef Level3Up = sc.Subgraph[2];
SCSubgraphRef Level1Down = sc.Subgraph[3];
SCSubgraphRef Level2Down = sc.Subgraph[4];
SCSubgraphRef Level3Down = sc.Subgraph[5];

if (sc.SetDefaults)
{
sc.GraphName = "Line Tool Projections";
sc.AutoLoop = 0;

Level1.Name = "Projection Level 1 (points)";
Level1.SetInt(9);

Level2.Name = "Projection Level 2 (points)";
Level2.SetInt(13);

Level3.Name = "Projection Level 3 (points)";
Level3.SetInt(19);

ShowLevelValues.Name = "Show Level Value Labels";
ShowLevelValues.SetYesNo(1);

// Subgraph settings
Level1Up.Name = "Level 1 Up";
Level1Up.DrawStyle = DRAWSTYLE_LINE;
Level1Up.PrimaryColor = RGB(0, 255, 0);

Level2Up.Name = "Level 2 Up";
Level2Up.DrawStyle = DRAWSTYLE_LINE;
Level2Up.PrimaryColor = RGB(0, 200, 0);

Level3Up.Name = "Level 3 Up";
Level3Up.DrawStyle = DRAWSTYLE_LINE;
Level3Up.PrimaryColor = RGB(0, 150, 0);

Level1Down.Name = "Level 1 Down";
Level1Down.DrawStyle = DRAWSTYLE_LINE;
Level1Down.PrimaryColor = RGB(255, 0, 0);

Level2Down.Name = "Level 2 Down";
Level2Down.DrawStyle = DRAWSTYLE_LINE;
Level2Down.PrimaryColor = RGB(200, 0, 0);

Level3Down.Name = "Level 3 Down";
Level3Down.DrawStyle = DRAWSTYLE_LINE;
Level3Down.PrimaryColor = RGB(150, 0, 0);

return;
}

if (sc.UpdateStartIndex != sc.ArraySize - 1)
return;

const int ToolType = static_cast<int>(DRAWING_LINE);
const int DrawingCount = sc.GetUserDrawnDrawingsCount(sc.ChartNumber, ToolType);

if (DrawingCount == 0)
{
sc.AddMessageToLog("LineToolProjections: No line drawings found.", 0);
return;
}

for (int i = DrawingCount - 1; i >= 0; --i)
{
s_UseTool Tool;
if (!sc.GetUserDrawnChartDrawing(sc.ChartNumber, i, Tool, ToolType))
continue;

if (Tool.DrawingType != static_cast<DrawingTypeEnum>(DRAWING_LINE))
continue;

float High = max(Tool.BeginValue, Tool.EndValue);
float Low = min(Tool.BeginValue, Tool.EndValue);

float Level1Val = static_cast<float>(Level1.GetInt());
float Level2Val = static_cast<float>(Level2.GetInt());
float Level3Val = static_cast<float>(Level3.GetInt());

float Levels[6] = {
High + Level1Val,
High + Level2Val,
High + Level3Val,
Low - Level1Val,
Low - Level2Val,
Low - Level3Val
};

// Plot subgraph values
Level1Up[sc.Index] = Levels[0];
Level2Up[sc.Index] = Levels[1];
Level3Up[sc.Index] = Levels[2];
Level1Down[sc.Index] = Levels[3];
Level2Down[sc.Index] = Levels[4];
Level3Down[sc.Index] = Levels[5];

// Draw horizontal projected lines
for (int j = 0; j < 6; ++j)
{
s_UseTool LineTool;
LineTool.Clear();
LineTool.ChartNumber = sc.ChartNumber;
LineTool.DrawingType = static_cast<DrawingTypeEnum>(DRAWING_LINE);
LineTool.BeginValue = Levels[j];
LineTool.BeginDateTime = sc.BaseDateTimeIn[sc.ArraySize - 1].GetAsDouble();
LineTool.Color = RGB(0, 255, 0);
LineTool.AddMethod = UTAM_ADD_ALWAYS;

if (ShowLevelValues.GetYesNo())
{
char Label[32];
snprintf(Label, sizeof(Label), "%.2f", Levels[j]);
LineTool.Text = Label;
}

sc.UseTool(LineTool);
}

break; // Only process most recent line
}
}
[2025-06-10 08:16:59]
User431178 - Posts: 711

thank you for your help. I am still not there. Build works but no lines are projected. I made the changes that you suggested above. i am getting the following in the message log: 2025-06-09 21:00:06.631 | Chart: ESM25_FUT_CME [CB][M] 5 Min #7 | Study: Line Tool Projections | LineToolProjections: No line drawings found. Here is the code with changes you suggested.


const int DrawingCount = sc.GetUserDrawnDrawingsCount(sc.ChartNumber, ToolType);

should be as below, drawing type is not used here


const int DrawingCount = sc.GetUserDrawnDrawingsCount(sc.ChartNumber, 0);


if (!sc.GetUserDrawnChartDrawing(sc.ChartNumber, i, Tool, ToolType))
continue;

should be as below, you have things in the wrong order


if (!sc.GetUserDrawnChartDrawing(sc.ChartNumber, DRAWING_LINE, Tool, i))
continue;

If you want the last added / modified drawing you can dispense with the loop and simply enter -1 as the drawing index



if (!sc.GetUserDrawnChartDrawing(sc.ChartNumber, DRAWING_LINE, Tool, -1))
return;




#ifndef DRAWING_LINE
#define DRAWING_LINE 8
#endif

What is the purpose of this?

DRAWING_LINE is defined by DrawingTypeEnum and has a value of 1, you can simply use the existing enum value as the function argument.
When you cast your "DRAWING_LINE" to DrawingTypeEnum it becomes DrawingTypeEnum::DRAWING_RETRACEMENT.



// Plot subgraph values
Level1Up[sc.Index] = Levels[0];
Level2Up[sc.Index] = Levels[1];
Level3Up[sc.Index] = Levels[2];
Level1Down[sc.Index] = Levels[3];
Level2Down[sc.Index] = Levels[4];
Level3Down[sc.Index] = Levels[5];

You are using sc.AutoLoop = 0, therefore sc.Index would not be used, here you would need sc.ArraySize-1 instead (for example).


// Draw horizontal projected lines
for (int j = 0; j < 6; ++j)
{
s_UseTool LineTool;
LineTool.Clear();
LineTool.ChartNumber = sc.ChartNumber;
LineTool.DrawingType = DRAWING_LINE; // static_cast<DrawingTypeEnum>(DRAWING_LINE);
LineTool.BeginValue = Levels[j];
LineTool.BeginDateTime = sc.BaseDateTimeIn[sc.ArraySize - 1].GetAsDouble();
LineTool.Color = RGB(0, 255, 0);
LineTool.AddMethod = UTAM_ADD_ALWAYS;


You need to set an end date time and price for your line, both anchors are needed for it to be drawn.
You can also drop the static cast and just use the enum value when setting the drawing type.


if (ShowLevelValues.GetYesNo())
{
char Label[32];
snprintf(Label, sizeof(Label), "%.2f", Levels[j]);
LineTool.Text = Label;
}

Here you can use sc.FormatGraphValue instead or even


LineTool.Text.Format("%.2f", Levels[j])

It might pay to read some of the docs about drawing tools (and other items).
Using Drawing Tools From an Advanced Custom Study


One other thing, the way you have it written, every time the function is called (every chart update) it will add more lines to the chart, 6 on each call, on top of the previous ones.
You may wish to remember which line you have added lines for and/or remember the lines added and update them instead.
Persistent variables can help you with that.

ACSIL Interface Members - Functions: Persistent Variable Functions
[2025-06-10 17:40:52]
User936417 - Posts: 16
Thanks for your help I will continue this as time permits. There is a lot more to it than I imagined!

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

Login

Login Page - Create Account