Coding a Journal indicator for SierraChart - futures io
futures io



Coding a Journal indicator for SierraChart


Discussion in Sierra Chart

Updated
      Top Posters
    1. looks_one shokunin with 17 posts (52 thanks)
    2. looks_two Futures Operator with 1 posts (0 thanks)
    3. looks_3 cory with 1 posts (0 thanks)
    4. looks_4 ninjus with 1 posts (1 thanks)
    1. trending_up 4,797 views
    2. thumb_up 53 thanks given
    3. group 16 followers
    1. forum 20 posts
    2. attach_file 0 attachments




Welcome to futures io: the largest futures trading community on the planet, with well over 150,000 members
  • Genuine reviews from real traders, not fake reviews from stealth vendors
  • Quality education from leading professional traders
  • We are a friendly, helpful, and positive community
  • We do not tolerate rude behavior, trolling, or vendors advertising in posts
  • We are here to help, just let us know what you need
You'll need to register in order to view the content of the threads and start contributing to our community.  It's free and simple.

-- Big Mike, Site Administrator

(If you already have an account, login at the top of the page)

 
Search this Thread
 

Coding a Journal indicator for SierraChart

(login for full post details)
  #1 (permalink)
 shokunin 
Manchester, United Kingdom
 
Experience: Advanced
Platform: Sierra Chart
Broker: Optimus Futures, Rithmic, Denali
Trading: ES
 
Posts: 71 since Jul 2020
Thanks: 6 given, 126 received

Introduction

I've decided to write my own journaling software - as a study for SierraChart. This will let me journal my trades in real time, and make journaling a natural part of my workflow rather than a chore or afterthought.

I will document my progress in this forum post:
  • My first experience of ACSIL and getting started with C++
  • The concepts, design and high level architecture
  • Problems encountered, solutions and workarounds
  • Code examples

Whilst it will be part technical (C++, ACSIL and general programming concepts), I will also discuss how I see and trade the market, and the information I want to record to make me a better trader. Hopefully this will make it interesting for general traders that have no interest in SierraChart or coding.

Started this thread Reply With Quote
The following 8 users say Thank You to shokunin for this post:

Can you help answer these questions
from other members on futures io?
NT8 - Footprint Chart adding on code
NinjaTrader
Learning Day Trading, need some advice on approach advice
Traders Hideout
 
 
(login for full post details)
  #2 (permalink)
 shokunin 
Manchester, United Kingdom
 
Experience: Advanced
Platform: Sierra Chart
Broker: Optimus Futures, Rithmic, Denali
Trading: ES
 
Posts: 71 since Jul 2020
Thanks: 6 given, 126 received

My background
I've been a programmer for over 30 years. I started writing assembly language on 8-bit 6502 and Z80 CPUs, and most recently I've written quantitative analysis software using Python and automated trading bots for InteractiveBrokers' TWS.

I've been a daytrader for the past 3 years. I learnt to daytrade during the last crypto boom and now I mainly trade ES futures. I am a discretionary trader and do not follow a set system. I do not use indicators and trade purely based on fomo market structure and order flow.


The initial goal
I currently use Jigsaw Journalytix. The statistic I most care about is Maximum Adverse Excursion (MAE). However, for some reason Journalytix does not calculate this accurately. For example, sometimes I know a trade has gone 2-3 ticks against me on initial entry, but Journalytix will often report 0 MAE.

I find MAE important because it tells me if I can bring my stop closer. The closer I can bring my stop to entry, the better my risk/reward.

In addition, I want to know:
  1. Am I entering too early or too late?
  2. Am I exiting too early or too late?
  3. Am I moving my stop to breakeven too soon?

Journalytix cannot answer these questions because it only records MAE and MFE from entry to exit. I need to calculate the potential MAE and MFE on either side of my entry and exit as well, to see if an earlier entry or a later exit would be profitable.


Basic plan
I'm not really a planner and prefer to make things up as I go along. However, this was the basic plan when I started:
  1. Pick an IDE and get familiar with C++
  2. Understand ACSIL concepts, get the API, look at sample code
  3. Write a simple "Hello, world!" study
  4. This will likely grow into a larger project, so build a workflow and framework for SierraChart indicators
  5. Come up with a high level software design; classes, data structures. I want the business logic to be kept separate from the SierraChart integration and User Interface. If I move to a different platform in the future, I'll only need to rewrite the platform-specific parts.
  6. Figure out how best to integrate the journal controls in SierraChart so that operation becomes part of my natural trading workflow and not an afterthought or chore.
  7. Display stats in real time.
  8. Export end-of-day stats to a database.

Started this thread Reply With Quote
The following 5 users say Thank You to shokunin for this post:
 
(login for full post details)
  #3 (permalink)
 shokunin 
Manchester, United Kingdom
 
Experience: Advanced
Platform: Sierra Chart
Broker: Optimus Futures, Rithmic, Denali
Trading: ES
 
Posts: 71 since Jul 2020
Thanks: 6 given, 126 received


Choosing the IDE

If I was a really advanced programmer like this guy on YouTube, I would write my code in Microsoft Word. However, I decided to play safe and stick to the more traditional method of using an IDE (Integrated Development Environment). SierraChart indicators are written in C++, so I need an IDE for C++.
  • Microsoft Visual Studio (free)
  • JetBrains CLion (not free)

Visual Studio is often a default option but it feels too much like work to me. This is supposed to be a fun project. So I decided to splash out on JetBrains CLion. I already use JetBrains' Python IDE and I like it a lot, so it was a no brainer for me to just go with CLion.

Started this thread Reply With Quote
The following user says Thank You to shokunin for this post:
 
(login for full post details)
  #4 (permalink)
 shokunin 
Manchester, United Kingdom
 
Experience: Advanced
Platform: Sierra Chart
Broker: Optimus Futures, Rithmic, Denali
Trading: ES
 
Posts: 71 since Jul 2020
Thanks: 6 given, 126 received

Getting familiar with C++

Java/C#/Python assign by reference as default, and C++ assigns by value as default.

Pseudocode:
 
Code
a = Cat
b = a
feed(a)
In Java/C#/Python, we end up with one actual Cat with two names ("a" and "b"). So you could feed "a" or "b" and it would be the same end result as they both refer to the same actual object. In C++ we end up with two actual Cats (one called "a" and one called "b"). "a" is a different actual object than "b". So if you feed "a", "b" will still be hungry.

If you want c++ to pass by reference, you can use the & symbol to pass by reference, or you can use the * to specify a pointer to the memory location of the object. Pass by reference and Pass by pointer are fast because a copy does not need to be made. However, if you're sending your object to a function, you need to trust that function doesn't do stuff to your object that you don't want. c++ has the 'const' keyword, which guarantees the function will treat your object as read only, and not make any changes.

If the object you want to pass to a function is no longer needed by your code, you can "move" it. This is functionally equivalent to passing by value, except that instead of sending a copy of your object, your actual object is sent.

In summary, there are 4 ways to pass objects around:
  1. By Value - object is copied. Safe, but slow.
  2. By Reference (&) - the actual object is passed rather than a copy. This is fast. The 'const' keyword states the object won't be modified.
  3. By Pointer (*) - a pointer to a memory location containing the object is passed.
  4. By Move - this is like By Value except the copy doesn't happen; your object is just given to the function. This only works if the calling code no longer needs the object.

It is possible that a Pointer points to an object that has subsequently been removed from memory. This can cause a program crash. It is up to you to make sure this doesn't happen. Also, if you create objects on Heap memory, it is up to you to delete them. Otherwise you will get a memory leak.

Once you understand these concepts and differences, everything else is just a matter of stackoverflow syntax.

I really like C++. A lot. I'm not sure it would have been my first choice for the F35 Joint Strike Fighter though.

Started this thread Reply With Quote
The following 2 users say Thank You to shokunin for this post:
 
(login for full post details)
  #5 (permalink)
 shokunin 
Manchester, United Kingdom
 
Experience: Advanced
Platform: Sierra Chart
Broker: Optimus Futures, Rithmic, Denali
Trading: ES
 
Posts: 71 since Jul 2020
Thanks: 6 given, 126 received

High level structure

I want to be able to differentiate between a longer swing position and an interim scalp. For example, I may hold a short with a target of 40 ticks, and during that time I may take a long for 8 ticks. I view this as two completely separate trades.

I also want to be able to support scale-in/scale-out.

I have come up with names for the main classes and data structures:
  • Journal - this is the highest level object and contains all data for all time.
  • Playbook - a collection of strategies.
  • Strategy - a type of trade idea, e.g. a chart pattern, type of order flow, or other event that may be tradeable. A strategy may require a certain type of market condition to be valid.
  • Market Character - classification of market condition.
  • Opportunity - when a strategy has been identified.
  • Orderfill - Orderfills are allocated to an opportunity.
  • Session - a defined period of time that neatly groups opportunities for review. For a daytrader, this might be 0930-1600 for each trading day.

I have opted not to use the term 'Trade', and instead chose 'Opportunity'. Trade is already used to mean a single transaction between two parties. For example, if you watch the Time and Sales, each entry is a Trade consisting of time, volume and price. I would find it confusing to reuse the term Trade in this context.

It is possible that I would identify opportunities on the chart and not execute them, and I can collect stats on that as well.

Started this thread Reply With Quote
The following 3 users say Thank You to shokunin for this post:
 
(login for full post details)
  #6 (permalink)
 ninjus 
Strat Enthusiast
Chiang Mai Thailand
 
Experience: Beginner
Platform: Seirra Chart
Broker: Optimus + Denali
Trading: MNQ
 
ninjus's Avatar
 
Posts: 734 since Jun 2017
Thanks: 1,209 given, 2,332 received

This is relevant to my interests

It you need a beta tester at any stage let me know.

Sent using the futures.io mobile app


Marcus Aurelius
"Not to assume it's impossible because you find it hard. But to recognize that if it's humanly possible, you can do it too"

Follow me on Twitter Visit my futures io Trade Journal Reply With Quote
The following user says Thank You to ninjus for this post:
 
(login for full post details)
  #7 (permalink)
 shokunin 
Manchester, United Kingdom
 
Experience: Advanced
Platform: Sierra Chart
Broker: Optimus Futures, Rithmic, Denali
Trading: ES
 
Posts: 71 since Jul 2020
Thanks: 6 given, 126 received

The first issue

The first issue I encountered with SierraChart was actually getting my code to compile. SierraChart was designed to use the C++ compiler provided with the Build Tools from Visual Studio 2015. However, it doesn't work with 2017 or 2019.
This post on the SC Board seems to be related to the same issue, but doesn't provide a solution.

When I ask SierraChart to compile and install my code, it creates and runs a batch file called VisualCCompile.Bat. VisualCCompile.Bat in turn calls vcvarsall.bat which configures the build environment ready for compiling. However, the location of vcvarsall.bat has changed between 2015 and 2019 and SierraChart is still looking in the old location.

SierraChart checks an environment variable called VS140COMNTOOLS that defines where the location of vcvarsall.bat is located. So it should just be a case of changing the environment variable from the 2015 default to the new location required by 2019: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat. Unfortunately this doesn't work either, because SierraChart incorrectly tries to insert a /vc/ at the end of the path - helpful for 2015 but not for 2019.

I opened this support ticket with SierraChart about the issue and it seems they are going to fix the issue in the next release. For now, I have created a dummy vcvarsall.bat file where SierraChart expects to find it, and I point that to the vcvarsall.bat where Microsoft actually puts it.

That took way longer than it should have.

Started this thread Reply With Quote
The following 2 users say Thank You to shokunin for this post:
 
(login for full post details)
  #8 (permalink)
 shokunin 
Manchester, United Kingdom
 
Experience: Advanced
Platform: Sierra Chart
Broker: Optimus Futures, Rithmic, Denali
Trading: ES
 
Posts: 71 since Jul 2020
Thanks: 6 given, 126 received

The second issue

As I'm developing a larger project, I want to organise my code into several files. SierraChart allows this, but the interface is not very intuitive. You need to specify all the files to compile in a single line, and then the resulting .dll is named after the first file in the line, regardless of what you actually want it to be called. I opened this support ticket.

As a workaround, I'm asking SierraChart to compile a single .cpp file, and that .cpp file includes all the other files in my project.


Organising my project

I've come up with a file structure which seems to work quite nicely with SierraChart:
 
Code
/myCode/
  # This folder contains my classes, data structures and business logic.
  # There are no SierraChart references here.
  myFile.cpp
  myFile.h
  myFile2.cpp
  myFile2.h
  ..

/myCode_tests/
  # I use test driven development for my library code.
  # The test files are kept here.
  myFile_test.cpp
  myFile2.cpp
  ..

/sierraStudies/
  # This folder contains SierraChart specific code.
  # The studies here can include ../myCode/whatever.h
  # The studies here can include ../sierrachart.h
  myStudy1.cpp
  myStudy2.cpp
  ..

/
  # This folder contains the SierraChart header files (copied from ACS_SOURCE)
  myAwesomeStudyCollection.cpp   # Named after the SCDLLName

The master myAwesomeStudyCollection.cpp file looks like this:
 
Code
#include "sierrachart.h"

SCDLLName("myAwesomeStudyCollection");

#include "mycode/myFile.cpp"
#include "mycode/myFile2.cpp"
#include "sierraStudies/myStudy1.cpp"
#include "sierraStudies/myStudy2.cpp"

Started this thread Reply With Quote
The following user says Thank You to shokunin for this post:
 
(login for full post details)
  #9 (permalink)
 shokunin 
Manchester, United Kingdom
 
Experience: Advanced
Platform: Sierra Chart
Broker: Optimus Futures, Rithmic, Denali
Trading: ES
 
Posts: 71 since Jul 2020
Thanks: 6 given, 126 received

Test Driven Development

I spent some time looking at the different testing frameworks for C++.

Google Test
This was the first framework I looked at, but I found it large and cumbersome. I decided to avoid Google Test for similar reasons that I avoided Visual Studio. I wanted something that was header only, so I could simply drop the source files into my folder structure.

The advantage of Google Test is it allows assertions and exceptions to be caught. But for this project, I won't need this functionality.

Doctest
This was actually my preferred choice, but I couldn't get it to work under CLion. It turns out Doctest had released a new version, but CLion hadn't updated their code yet, so it was necessary to modify the version number of the Doctest code for things to work. I don't like issues and workaround like that, so I decided not to use DocTest. I think this is more an issue with CLion that Doctest, and I would probably have used Doctest otherwise.

Catch2
I realised that the person who wrote Catch2 (Phil Nash) is actually a staff member and advocate for CLion. So this pretty much sealed the deal; I'm unlikely to get better test integration with my IDE than this.

Started this thread Reply With Quote
The following user says Thank You to shokunin for this post:
 
(login for full post details)
  #10 (permalink)
 shokunin 
Manchester, United Kingdom
 
Experience: Advanced
Platform: Sierra Chart
Broker: Optimus Futures, Rithmic, Denali
Trading: ES
 
Posts: 71 since Jul 2020
Thanks: 6 given, 126 received


Sketching out the user interface
I've been thinking about how I actually want the User Interface within SierraChart to operate. The easiest method would be to use Hotkeys to select the different orderfills and opportunities. When SierraChart detects a keypress it will call the study along with the keycode pressed. So this would be ideal to begin and get things going with minimum coding so I can test the concept.

The initial plan is to use the numeric keypad left/right to select an orderfill, and up/down to select an opportunity. I'll use Enter to assign the orderfill to the opportunity.

SierraChart already displays orderfills as small triangles (Trade menu > Show Order Fills) so I will use the left/right hotkeys to scroll through each orderfill. A yellow circle will highlight the selected orderfill.


Operational modes
Trying to envisage how this would work in my head, I see three states:
  • Clean - This hides everything.
  • Assign - This is when I'm mapping an orderflow to an opportunity.
  • View - This is when I'm viewing an opportunity and want to see stats such as time in trade, average entry price, MAE/MFE, P&L, risk, etc.

Scrolling through the orderfills should be straightforward as they are ordered according to timestamp.
Scrolling through the opportunities will be slightly more complex as the timestamp order of each opportunity will change depending on the orderfills allocated to it.
In addition to scrolling through all opportunities, I want to also include an "Add new" opportunity, and an "Unassigned" opportunity, which shows stats for any orderfills that have not yet been assigned.

A natural order to scroll through opportunities would seem to be:
earliest > .. > latest > addNew > unassigned

However, I don't know if this is going to be the right choice until I can try it for real.


Code
I'll use the State design pattern to process the hotkeys differently for each state. I've put together this outline and commented the objectives so I don't forget. After breakfast I'll try and get this working.

JournalData is a business object that is stored using SierraChart's persistent data storage, hence I'm using the generic variable name pd for now.

 
Code
namespace SierraStudy {

    namespace JournalState {

        class Base {
        public:
            virtual void ProcessKeypress(SCStudyInterfaceRef sc, JournalData *pd) = 0;

            virtual void AddDisplayElements(SCStudyInterfaceRef sc, JournalData *pd) = 0;
        };


        class Clean : public Base {
        public:
            Clean() = default;

            void ProcessKeypress(SCStudyInterfaceRef sc, JournalData *pd) override {
                // Pressing left/right enters Assign mode
                // Pressing Home/End enters Assign mode and changes the selected orderfill to first/last
                //      and scrolls to that orderfill

                // Pressing up/down enters View mode
                // Pressing PgDn/PgUp enters View mode and changes the selected opportunity to first/unassigned
            }

            void AddDisplayElements(SCStudyInterfaceRef sc, JournalData *pd) override {

            }
        };


        class Assign : public Base {
        public:
            Assign() = default;

            void ProcessKeypress(SCStudyInterfaceRef sc, JournalData *pd) override {
                // Left/Right/Home/End selects the orderfill and scrolls to that orderfill

                // Up/Down/PgUp/PgDn selects the target opportunity
                //      Order: First..Last, New, Unassigned

                // Enter assigns the orderfill to the opportunity
                // Exit returns to Clean mode
            }

            void AddDisplayElements(SCStudyInterfaceRef sc, JournalData *pd) override {

            }
        };


        class View : public Base {
        public:
            View() = default;

            void ProcessKeypress(SCStudyInterfaceRef sc, JournalData *pd) override {
                // Up/Down/PgUp/PgDn selects the opportunity to view stats on
                //      Order: first..last, unassigned

                // Exit returns to Clean mode

                // Pressing left/right enters Assign mode
                // Pressing Home/End enters Assign mode and changes the selected orderFill to first/last
                //     and scrolls to that orderfill
            }

            void AddDisplayElements(SCStudyInterfaceRef sc, JournalData *pd) override {

            }
        };

    }

}

Started this thread Reply With Quote
The following 2 users say Thank You to shokunin for this post:


futures io Trading Community Platforms and Indicators Sierra Chart > Coding a Journal indicator for SierraChart


Last Updated on April 5, 2022


Upcoming Webinars and Events
 

NinjaTrader Indicator Challenge!

Ongoing
     



Copyright © 2022 by futures io, s.a., Av Ricardo J. Alfaro, Century Tower, Panama, Ph: +507 833-9432 (Panama and Intl), +1 888-312-3001 (USA and Canada), info@futures.io
All information is for educational use only and is not investment advice.
There is a substantial risk of loss in trading commodity futures, stocks, options and foreign exchange products. Past performance is not indicative of future results.
no new posts