Building Sierra Chart Custom Studies

My notes on coding against Sierra Chart’s API

Photo by Miguel A. Amutio on Unsplash

Risk Disclaimer

Please read the Risk Disclaimer before reading this post.

Introduction

I will be using this post to keep track of my notes as I learn my way around Sierra Chart’s C++-based API.

The Sierra Charts help documentation seems pretty complete, which is great. Kudos to them for taking the time to put together thorough documentation.

A link to the original source is provided in this post where text is directly copied from the Sierra Chart website.

The Basics

  • Sierra Charts provides something called the “Custom Study Interface and Language (ACSIL)” for building custom code against their platform.
  • A “Custom Study” seems to be the generic name used for any custom code written against their platform.
  • The sc. prefix is used for built-in functions.
  • A study is contained within a single Chart Region. I am not sure what this means yet. Source.

Setting Up The Sierra Charts Development Environment

Annoyingly, Sierra Charts installs its own, outdated version of Notepad++.

I followed these steps to tell Sierra Charts to use my default installation of Notepad++ for code editing:

  • Click Analysis -> Build Custom Studies DLL.
  • Click File -> Select Editor.
  • Select Yes at the prompt.
  • Click Folder.
  • Select your notepad++ installation folder (mine was c:\Program Files\Notepad++), then click OK.
  • In the list of files that appears, select notepad++.exe. It should then appear in the “File Name” text box.
  • Click Open.

Notes On C++ In Sierra Charts

These are taken from reading the Sierra Chart documentation. Some are direct quotes (links to pages where the quote can be found are included where this is the case).

Looping Source.

  • The preferred method of looping is Automatic Looping. Source.
    • Automatic looping is activated by setting sc.AutoLoop = 1.
  • Array bounds are safe by default.
    • If you go under the minimum, it will return index zero.
    • If you go over the maximum, it will return index array_size - 1.
  • You can always use sc.Index to get the current array index.
    • e.g. sc.BaseData[SC_LAST][sc.Index].
  • The main arrays are:
    1. sc.BaseData[x][y] - the main price data on the chart.
      • x is used for specifying what you are looking for (which data set). 0 is the leftmost bar on the chart.
      • y is used for the index of the specific piece of data you are looking for.
      • e.g. sc.BaseData[SC_LAST][0] is the first bar in the timeseries’ close price
      • The size of the second array can also be determined by sc.BaseData[0].GetArraySize().
    2. sc.BaseDateTimeIn[] - contains SCDateTime variables for the bars in the chart.
      • 0 is the leftmost bar on the chart.
      • Always contains the open time of the bar in question.
    3. sc.DateTimeOut[] - I don’t get what the documentation is saying here, and I saw a forum post where the Sierra Charts team advises someone not to use this array.
    4. sc.Subgraph[].Data[] (shorthand notation: sc.Subgraph[][]) - are for your studies displayable output and can be used to hold the results of background or intermediate calculations.
    5. sc.Subgraph[].Arrays[][] - can be used to hold the results of background or intermediate calculations for a sc.Subgraph[].Data[] array that is graphed on the chart.
  • When your study function uses automatic looping, then it is automaticaly called once for every bar or column in the chart when the study is initially calculated.
    • If there are 100 bars in the chart, then it will be called 100 times when your study is initially calculated.
    • After that, the study function is called as the latest bar is updated and new bars are added.
  • sc.UpdateAlways can be used to run code on an interval Source.
    • The update interval is set through Global Settings >> General Settings >> Chart Update Interval.

Arrays Source

  • sc.BaseDataIn[][] / sc.BaseData[][] (both are the same thing) is an array of float arrays that contain the data for the main graph in the chart.
    • To get the current opening price: sc.BaseDataIn[SC_OPEN][sc.Index]
    • We can get bid volume, OHLC, uptick volume etc. from this array. See the source link for a complete listing.
  • sc.Subgraph[] is an array of the subgraphs available to the study.

    • Subgraphs are used for both drawing and holding data.
    • If you give a subgraph a name, it will appear in the chart.
    • Useful for debugging:
      • Set draw style to DRAWSTYLE_IGNORE.
      • Then view the data in Window >> Chart Values Window.
    • Example:

      // Make a reference to the second Subgraph and call it PlotB
      SCSubgraphRef PlotB = sc.Subgraph[1];
      
      // Now the PlotB reference can be used in place of sc.Subgraph[1]
      
      // Set the value of the element in the Subgraph Data array the
      // current index to 10.
      
      // This is the same as sc.Subgraph[1][sc.Index] = 10.0f;
      PlotB[sc.Index] = 10.0f; 
      
      // Calculate the simple moving average and store the result in
      // the Data array of PlotB (sc.Subgraph[1]).
      sc.SimpleMovAvg(sc.BaseDataIn[SC_LAST], PlotB, 20);
      
    • To get data, use sc.Subgraph[].Data[] / sc.Subgraph[][]

    • sc.Subgraph[0][sc.Index] is equivalent to sc.Subgraph[0].Data[sc.Index].

Automated Trading With ACSIL Source 1 Source 2

  • Main functions:
    • sc.BuyEntry
    • sc.BuyExit
    • sc.SellEntry
    • sc.SellExit
  • The steps for crating a new ACSIL automated trading system can be found here.
  • Having more than one automated trading system for the same symbol at the same time can only be done if each chart that has the automated trading system study is using a different Trade Account.
  • Important variables:
    • GlobalTradeSimulationIsOn: Simulation mode on or off.
    • AllowMultipleEntriesInSameDirection
    • MaximumPositionAllowed: Maximum number of open positions allowed.
    • SupportReversals: Allows entries in the opposite direction. Flattens existing positions if they exist.
    • SendOrdersToTradeService: If false, simulate. If true, send orders to broker. Link.
    • AllowOppositeEntryWithOpposingPositionOrOrders: How is this different to SupportReversals? I will probably find out when I begin coding against this API.
    • SupportAttachedOrdersForTrading: Allow SL and TP levels to be set.
    • CancelAllOrdersOnEntriesAndReversals: Cancel all non-market orders when submitting a new order.
    • CancelAllOrdersOnReversals: I need to re-read this one. Hopefully all will become clear when I start coding against the API.
    • AllowEntryWithWorkingOrders: Same as above.
    • CancelAllWorkingOrdersOnExit: Same as above.
    • SupportTradingScaleIn: Same as above.
    • SupportTradingScaleOut: Same as above.
  • To re-read: Differences Between Live Automated Trading and Simulated Automated Trading Source.

Backtesting Source

  • Useful functions: sc.IsReplayRunning: returns TRUE (1) if a replay is running on the chart the study instance is applied to or the replay is paused. Source.

General

  • Custom header files need to be placed above the #include "sierrachart.h" directive. Source.
  • The Windows.h and standard C++ library header files are already included. Source.
  • You don’t need to reload the studies on your chart every time you compile unless you made changes in the sc.SetDefaults code block. Source.
    • If you have made these changes, you need to remove the study from the chart and re-add it.
  • If your code throws exceptions (invalid access or divide by zero), you need to restart Sierra Chart. Source.
  • Entry point functions must always begin with the prefix scsf_. Source.
  • It is not recommended you work with C++ native arrays. Source.
    • It is always recommended to use the Sierra Chart sc.Subgraph[].Data and sc.Subgraph[].Arrays[] arrays to store your output data and background calculations.
    • The reason for this is simplicity and safety because these arrays are safe and the bounds can never be overwritten.
  • Use sc.AddMessageToLog() instead of cout. Source.
  • An alternative method to access a sc.Subgraph[].Data array element is available. Source.
    • Example: sc.Subgraph[0][sc.Index] is equivalent to sc.Subgraph[0].Data[sc.Index]
  • sc.Input[] is an array of the Inputs that a study can use. Source.
    • Maximum input count = 128.
  • To convert a string to a char *, use the function c_str(). Source.

    string testString = "Some text";
    sc.AddMessageToLog(baseMessage.c_str(), 1);
    
  • It seems from the documentation that the preference is to use Sierra Chart’s built-in string wrapper class SCString.

    • If using SCString and you need to pass it to something that uses a char* parameter, then you need to pass it SCString_instance.GetChars().
    • You can directly set this type using a string literal, e.g.

      SCString MessageText;
      MessageText = "Hello. This is a test.";
      
  • A Draw Style set to Ignore means that a subgraph is not painted on the chart.

  • The sc.BaseGraphValueFormat variable is an Integer indicating the Price Display Format/Value Format for the main graph in the chart. Source.

C++ Language Constructs

  • Pointers and dereferencing. Source.
    • An interesting property of pointers is that they can be used to access the variable they point to directly.
    • This is done by preceding the pointer name with the dereference operator (*).
    • The operator itself can be read as “value pointed to by”.
    • & is the address-of operator, and can be read simply as “address of”
    • * is the dereference operator, and can be read as “value pointed to by”
  • Literals. Source.

    // All of these are 75
    75         // decimal
    0113       // octal
    0x4b       // hexadecimal
    
    // Signed and unsigned
    75u        // unsigned int
    75l        // long
    75ul       // unsigned long 
    
    // Floating point numbers (defaults to double type)
    3.14159    // 3.14159
    6.02e23    // 6.02 x 10^23
    1.6e-19    // 1.6 x 10^-19
    3.0        // 3.0 
    
    // Other floating point literals
    3.14159L   // long double
    6.02e23f   // float 
    
  • Multi-line string literals. Source.

    "string expressed in \
    two lines" 
    
  • wchar_t string literals. Source.

    L"This is a wide character string"
    
  • Defining constants using a preprocessor directive. Source.

    #include <iostream>
    using namespace std;
    
    #define PI 3.14159
    #define NEWLINE '\n'
    
    int main ()
    {
        double r=5.0;               // radius
    
        double circle;
    
        circle = 2 * PI * r;
        cout << circle;
        cout << NEWLINE;
    
        return 0;
    }
    
  • Defining constants. Source.

    const int pathwidth = 100;
    const char tabulator = '\t';
    
  • Ternary conditional operator. Source.

    • Same syntax as C#, MQL, Java etc.

      condition ? result1 : result2
      
  • Ending execution. Source.

    void exit (int exitcode);
    
  • Passing parameters by reference. Source.

    void duplicate (int& a, int& b, int& c)
    {
    a*=2;
    b*=2;
    c*=2;
    }
    
  • Inline functions. Source.

    • Are like templates for functions.
    • Are inserted directly everywhere they are used, rather than being called to on the call stack.
  • Function prototypes. Source.

    int protofunction (int first, int second);
    int protofunction (int, int);
    

Useful Learning Resources

The Sierra Chart Documentation and Code Examples

As mentioned above, this is extensive and useful.

It also contains references to code samples included in the reference code, which can by default be found in the directory C:\SierraChart\ACS_Source.

It can be found here.

Onn Ben-Zvi

This chap’s videos and articles have been hugely useful to me.

I like to learn via a combination of reading and video content. His videos are helping to provide that missing link.

The content is old (from 2012), so there have been some changes in the way Sierra Chart’s code works since then.

That being said, the solutions to handling these changes are easily found on Sierra Chart’s support forums.

His YouTube channel can be found here, and his blog can be found here.

Futures.io

I joined this community a while ago and have been watching some of the webinars. I have yet to get to the point where I am actively contributing on the forums, although I am sure that time will come.

They have a forum section on Sierra Chart which can be found here.

YouTube C++ Tutorials

I found this tutorial very useful as I am a C# developer by trade.


Dmitri, who created this video, also has a really good PluralSight course which I have worked through.

Pluralsight

Pluralsight has a learning track dedicated to C++.

I am currently working through Kate Gregory’s “C++ Fundamentals Including C++ 17” course - it is excellent and I highly recommend it.

Editing And Debugging Sierra Charts Code In Visual Studio 2019

Visual Studio is my IDE of choice, especially with ReSharper installed.

I was busy figuring out how to get Sierra Charts code compiling in Visual Studio 2019, when I realised that I was perhaps trying to get too advanced too quickly.

I chose to rather open the folder C:\SierraChart\ACS_Source\ in Visual Studio, and carry on relying on Sierra Chart’s built-in ability to compile custom studies.

I followed this guide to get debugging from Visual Studio 2019 working.

Useful Sierra Charts Keyboard Shortcuts

  • Hand tool = Alt-H
  • Timeframes:
    • Change to 1M timeframe = 1, M, Return
    • Change to 1D timeframe = 1, D, Return
    • Etc.
Avatar
Scott Edwards
CTO / Head of Engineering

Lead software engineer, engineering manager, and beginner guitarist. I also have a strong interest in long-term investing.

Related