Login Page - Create Account

Support Board


Date/Time: Fri, 18 Apr 2025 06:47:27 +0000



[Programming Help] - C2447 error when compiling Advanced Custom Studies

View Count: 128

[2025-03-24 04:20:15]
User595847 - Posts: 5
Hello,

I’m encountering Error C2447: '(': missing function header (old-style formal list?) when I try to compile my custom strategy script. The error seems to be related to function headers or syntax, but I’m unable to pinpoint the exact cause.

I’ve tried reviewing the function definitions and headers, checked for missing function headers or syntax errors in my custom function declarations but to no avail.

If you could help pinpoint the problem and suggest how to fix the missing function header or any other related issues, I’d greatly appreciate it. Full script is below.

Thank you for your assistance!

Best regards,
Mark

#include "sierrachart.h"

SCDLLName("Trade Logic Strategy")

// Initialize study settings function
void InitializeStudy(SCStudyInterfaceRef sc)
{
if (sc.SetDefaults)
{
sc.GraphName = "Trade Logic Strategy";
sc.StudyDescription = "Automated strategy using predefined levels and opening range.";
sc.AutoLoop = 1;

// Inputs
sc.Input[0].Name = "Predefined Level";
sc.Input[0].SetFloat(4000.0);
sc.Input[1].Name = "Opening Range Start Time";
sc.Input[1].SetTime(HOURS(9) + MINUTES(30));
sc.Input[2].Name = "Tick Bar Size";
sc.Input[2].SetInt(2000);
sc.Input[3].Name = "Stop Loss (Ticks)";
sc.Input[3].SetInt(10);
sc.Input[4].Name = "Target Profit (Ticks)";
sc.Input[4].SetInt(20);
sc.Input[5].Name = "Order Quantity";
sc.Input[5].SetInt(1);

sc.AllowMultipleEntriesInSameDirection = false;
sc.MaximumPositionAllowed = 1;
sc.SupportReversals = false;
sc.SendOrdersToTradeService = false;
}
}

// Calculate Opening Range
void CalculateOpeningRange(SCStudyInterfaceRef sc, float &openingRangeHigh, float &openingRangeLow, bool &openingRangeSet)
{
SCDateTime now = sc.BaseDateTimeIn[sc.Index];
SCDateTime openingRangeStartTime = sc.Input[1].GetTime();

if (!openingRangeSet && now >= openingRangeStartTime && now < openingRangeStartTime + SCDateTime(0, 3600))
{
openingRangeHigh = max(openingRangeHigh, sc.High[sc.Index]);
openingRangeLow = min(openingRangeLow, sc.Low[sc.Index]);
}
else if (now > openingRangeStartTime + SCDateTime(0, 3600))
{
openingRangeSet = true;
}
}

// Check trade conditions
bool CheckTradeConditions(SCStudyInterfaceRef sc, float predefinedLevel, float openingRangeHigh, float openingRangeLow)
{
bool isAboveConditions = (sc.Close[sc.Index] > predefinedLevel) && (sc.Close[sc.Index] > openingRangeHigh);
bool isBelowConditions = (sc.Close[sc.Index] < predefinedLevel) && (sc.Close[sc.Index] < openingRangeLow);
return isAboveConditions || isBelowConditions;
}

// Execute the trade
void ExecuteTrade(SCStudyInterfaceRef sc, bool isAboveConditions, bool isBelowConditions, int orderQuantity, int stopLossTicks, int targetProfitTicks)
{
s_SCNewOrder NewOrder;
NewOrder.OrderType = SCT_ORDERTYPE_MARKET;
NewOrder.OrderQuantity = orderQuantity;
NewOrder.TimeInForce = SCT_TIF_GOOD_TILL_CANCELED;
NewOrder.AttachedOrderStopOffset = stopLossTicks * sc.TickSize;
NewOrder.AttachedOrderTargetOffset = targetProfitTicks * sc.TickSize;

if (isAboveConditions)
{
int result = sc.BuyEntry(NewOrder);
if (result > 0)
sc.AddMessageToLog("✅ Long trade executed", 0);
}
else if (isBelowConditions)
{
int result = sc.SellEntry(NewOrder);
if (result > 0)
sc.AddMessageToLog("✅ Short trade executed", 0);
}
}

// Main function: Sierra Chart entry point
SCSFExport void scsf_TradeLogicStrategy(SCStudyInterfaceRef sc)
{
// Initialize study settings
InitializeStudy(sc);

// Ensure valid index
if (sc.Index < 1)
return;

// Retrieve input values
float predefinedLevel = sc.Input[0].GetFloat();
int orderQuantity = sc.Input[5].GetInt();
int stopLossTicks = sc.Input[3].GetInt();
int targetProfitTicks = sc.Input[4].GetInt();

// Variables for opening range
static float openingRangeHigh = 0.0;
static float openingRangeLow = 0.0;
static bool openingRangeSet = false;

// Calculate the opening range
CalculateOpeningRange(sc, openingRangeHigh, openingRangeLow, openingRangeSet);

// Check if trade conditions are met
bool tradeConditionsMet = CheckTradeConditions(sc, predefinedLevel, openingRangeHigh, openingRangeLow);

// Execute trade if conditions are met
if (tradeConditionsMet)
{
ExecuteTrade(sc, (sc.Close[sc.Index] > predefinedLevel && sc.Close[sc.Index] > openingRangeHigh),
(sc.Close[sc.Index] < predefinedLevel && sc.Close[sc.Index] < openingRangeLow),
orderQuantity, stopLossTicks, targetProfitTicks);
}
}

[2025-03-24 09:30:18]
User431178 - Posts: 647
Post the whole complier error message next time, it may point directly to the error.

This is wrong for a start:

sc.Input[1].SetTime(HOURS(9) + MINUTES(30));

See this example in the docs:
ACSIL Interface Members - sc.Input Array: sc.Input[].SetTime()

Also you can construct an SCDateTime object and call the GetTime() member function:

SCDateTime(int Hour, int Minute, int Second, int Millisecond)


SCDateTime(9, 30, 0, 0).GetTime()

[2025-03-24 15:04:38]
cmet - Posts: 689
Incorrect study initialization. Not using valid ACSIL members.

This is one of the main issues when using GPT to help with ACSIL (along with green check emojis in notes ✅ 😶).

Make sure when you use it, you're forcing valid syntax.

This is not checked for functionality but it compiles and might get you thinking about the solutions you need:

#include "sierrachart.h"

SCDLLName("Trade Logic Strategy");

SCSFExport scsf_TradeLogicStrategy(SCStudyInterfaceRef sc)
{

//inputs

SCInputRef Input_Level = sc.Input[0];
SCInputRef Input_StartTime = sc.Input[1];
SCInputRef Input_Stop = sc.Input[3];
SCInputRef Input_Target = sc.Input[4];
SCInputRef Input_Quantity = sc.Input[5];

if (sc.SetDefaults)
{
sc.GraphName = "Trade Logic Strategy";
sc.StudyDescription = "Automated strategy using predefined levels and opening range.";
sc.AutoLoop = 1;

Input_Level.Name = "Predefined Level";
Input_Level.SetFloat(4000.0f);
Input_StartTime.Name = "Opening Range Start Time";
Input_StartTime.SetTime(HMS_TIME(9, 30, 0));
sc.Input[2].Name = "Tick Bar Size";
sc.Input[2].SetInt(2000);
Input_Stop.Name = "Stop Loss (Ticks)";
Input_Stop.SetInt(10);
Input_Target.Name = "Target Profit (Ticks)";
Input_Target.SetInt(20);
Input_Quantity.Name = "Order Quantity";
Input_Quantity.SetInt(1);

sc.AllowMultipleEntriesInSameDirection = false;
sc.MaximumPositionAllowed = 1;
sc.SupportReversals = false;
sc.SendOrdersToTradeService = false;

return;
}

if (sc.Index == 0)
return;

float predefinedLevel = Input_Level.GetFloat();
int orderQuantity = Input_Quantity.GetInt();
int stopLossTicks = Input_Stop.GetInt();
int targetProfitTicks = Input_Target.GetInt();

//opening range

const int date = sc.BaseDateTimeIn[sc.Index].GetDate();
int& r_LastDate = sc.GetPersistentInt(0);
float& r_High = sc.GetPersistentFloat(0);
float& r_Low = sc.GetPersistentFloat(1);
int& r_OpeningRangeSet = sc.GetPersistentInt(2);

//reset range on new session

if (date != r_LastDate)
{
r_LastDate = date;
r_OpeningRangeSet = 0;
r_High = sc.High[sc.Index];
r_Low = sc.Low[sc.Index];
}

//opening range

SCDateTime now = sc.BaseDateTimeIn[sc.Index];
SCDateTime openingRangeStartTime = Input_StartTime.GetTime();
SCDateTime openingRangeEndTime = openingRangeStartTime + 3600;

if (r_OpeningRangeSet == 0 && now >= openingRangeStartTime && now < openingRangeEndTime)
{
r_High = sc.High[sc.Index] > r_High ? sc.High[sc.Index] : r_High;
r_Low = sc.Low[sc.Index] < r_Low ? sc.Low[sc.Index] : r_Low;
}
else if (now >= openingRangeEndTime)
{
r_OpeningRangeSet = 1;
}

//wait for range set

if (r_OpeningRangeSet == 0)
return;

//trade conditions

float lastPrice = sc.Close[sc.Index];
bool isAboveConditions = (lastPrice > predefinedLevel) && (lastPrice > r_High);
bool isBelowConditions = (lastPrice < predefinedLevel) && (lastPrice < r_Low);
bool tradeConditionsMet = isAboveConditions || isBelowConditions;

//execution

if (tradeConditionsMet)
{
s_SCNewOrder NewOrder;
NewOrder.OrderType = SCT_ORDERTYPE_MARKET;
NewOrder.OrderQuantity = orderQuantity;
NewOrder.TimeInForce = SCT_TIF_GOOD_TILL_CANCELED;

NewOrder.Target1Offset = targetProfitTicks * sc.TickSize;
NewOrder.AttachedOrderTarget1Type = SCT_ORDERTYPE_LIMIT;

NewOrder.Stop1Offset = stopLossTicks * sc.TickSize;
NewOrder.AttachedOrderStop1Type = SCT_ORDERTYPE_STOP;

if (isAboveConditions)
sc.BuyEntry(NewOrder);
else if (isBelowConditions)
sc.SellEntry(NewOrder);
}
}

Date Time Of Last Edit: 2025-03-24 15:05:00
[2025-03-25 01:28:59]
User595847 - Posts: 5
Thanks so much, cmet, you have pointed me in the right direction. I am now testing in Sim, and have updated the script to reflect my full strategy. Script is below, in case it's of any benefit to you or others.

It is an ES/MES momentum strategy, where I use the predefined level (ie your chosen support/resistance), opening range and short term momentum from tick bar closes as filters for trend/momentum, with the ability to also set a specific time when the trade triggers eg 1 hour after opening range to avoid whipsaws. Then using trailing stop with initial stop referencing the opening range high/low. As I live in Australia, I wanted to automate my strategy for trading the US Cash Session for ES/MES, as I'm typically sleeping at this time.

#include "sierrachart.h"

SCDLLName("Trade Logic Strategy");

SCSFExport scsf_TradeLogicStrategy(SCStudyInterfaceRef sc)
{
// inputs
SCInputRef Input_Level = sc.Input[0];
SCInputRef Input_TimeRestrictionEnabled = sc.Input[1]; // Enable/Disable Time Restriction
SCInputRef Input_RestrictionStartTime = sc.Input[2]; // Start Time for Time Restriction
SCInputRef Input_Stop = sc.Input[3]; // Stop Loss in points from opening range
SCInputRef Input_Target = sc.Input[4]; // Target Profit in ticks
SCInputRef Input_Quantity = sc.Input[5]; // Order Quantity
SCInputRef Input_OpeningRangeDuration = sc.Input[6]; // Opening Range Duration in minutes
SCInputRef Input_OpeningRangeStartTime = sc.Input[7]; // Opening Range Start Time

if (sc.SetDefaults)
{
sc.GraphName = "Trade Logic Strategy";
sc.StudyDescription = "Automated strategy using predefined levels and opening range.";
sc.AutoLoop = 1;

// Define Inputs
Input_Level.Name = "Predefined Level";
Input_Level.SetFloat(4000.0f);

Input_TimeRestrictionEnabled.Name = "Enable Time Restriction";
Input_TimeRestrictionEnabled.SetYesNo(1); // Default to enabled

Input_RestrictionStartTime.Name = "Time Restriction Start Time";
Input_RestrictionStartTime.SetTime(HMS_TIME(11, 0, 0)); // Default start time at 11:00 AM ET

Input_Stop.Name = "Stop Loss (Points from Opening Range)";
Input_Stop.SetInt(3); // Default stop loss: 3 points from the opening range

Input_Target.Name = "Target Profit (Ticks)";
Input_Target.SetInt(20); // Default target profit: 20 ticks

Input_Quantity.Name = "Order Quantity";
Input_Quantity.SetInt(1); // Default quantity: 1 contract

Input_OpeningRangeDuration.Name = "Opening Range Duration (Minutes)";
Input_OpeningRangeDuration.SetInt(60); // Default duration: 60 minutes

Input_OpeningRangeStartTime.Name = "Opening Range Start Time";
Input_OpeningRangeStartTime.SetTime(HMS_TIME(9, 30, 0)); // Default start time for U.S. session (9:30 AM ET)

sc.AllowMultipleEntriesInSameDirection = false;
sc.MaximumPositionAllowed = 1;
sc.SupportReversals = false;
sc.SendOrdersToTradeService = false;

return;
}

if (sc.Index == 0)
return;

// Input values
float predefinedLevel = Input_Level.GetFloat();
int orderQuantity = Input_Quantity.GetInt();
int stopLossPoints = Input_Stop.GetInt(); // Stop loss points from the opening range
int targetProfitTicks = Input_Target.GetInt();
int openingRangeDuration = Input_OpeningRangeDuration.GetInt();
SCDateTime openingRangeStartTime = Input_OpeningRangeStartTime.GetTime();
bool timeRestrictionEnabled = Input_TimeRestrictionEnabled.GetYesNo() !=0; // Time restriction enabled/disabled
SCDateTime restrictionStartTime = Input_RestrictionStartTime.GetTime(); // Time restriction start time

// Opening range variables
const int date = sc.BaseDateTimeIn[sc.Index].GetDate();
int& r_LastDate = sc.GetPersistentInt(0);
float& r_High = sc.GetPersistentFloat(0);
float& r_Low = sc.GetPersistentFloat(1);
int& r_OpeningRangeSet = sc.GetPersistentInt(2);

// Reset range on new session
if (date != r_LastDate)
{
r_LastDate = date;
r_OpeningRangeSet = 0;
r_High = sc.High[sc.Index];
r_Low = sc.Low[sc.Index];
}

// Opening range logic
SCDateTime openingRangeEndTime = openingRangeStartTime + (openingRangeDuration * 60);
SCDateTime now = sc.BaseDateTimeIn[sc.Index];

if (r_OpeningRangeSet == 0 && now >= openingRangeStartTime && now < openingRangeEndTime)
{
r_High = sc.High[sc.Index] > r_High ? sc.High[sc.Index] : r_High;
r_Low = sc.Low[sc.Index] < r_Low ? sc.Low[sc.Index] : r_Low;
}
else if (now >= openingRangeEndTime)
{
r_OpeningRangeSet = 1;
}

// Wait for opening range to be set
if (r_OpeningRangeSet == 0)
return;

// Time restriction logic
if (timeRestrictionEnabled && now < restrictionStartTime)
return; // Exit if time restriction is enabled and before the restriction start time

// Trade conditions
float lastPrice = sc.Close[sc.Index];
bool isAboveConditions = (lastPrice > predefinedLevel) && (lastPrice > r_High);
bool isBelowConditions = (lastPrice < predefinedLevel) && (lastPrice < r_Low);
bool tradeConditionsMet = isAboveConditions || isBelowConditions;

// Execution logic
if (tradeConditionsMet)
{
s_SCNewOrder NewOrder;
NewOrder.OrderType = SCT_ORDERTYPE_MARKET;
NewOrder.OrderQuantity = orderQuantity;
NewOrder.TimeInForce = SCT_TIF_GOOD_TILL_CANCELED;

// Set stop loss and target from opening range
NewOrder.Stop1Offset = stopLossPoints * sc.TickSize;
NewOrder.Target1Offset = targetProfitTicks * sc.TickSize;

// Create and execute buy/sell orders
if (isAboveConditions)
sc.BuyEntry(NewOrder);
else if (isBelowConditions)
sc.SellEntry(NewOrder);
}
}

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

Login

Login Page - Create Account