Now, most of the trading systems in the market offer a fixed set of indicators which cannot be extended nor modified by the end users. These end users are professional traders and are expert in the algorithms behind the industry-standard indicators. They often want to tweak and play with the logic to fit their specific needs. Therefore, while we were working on the Sycap Chart project, we decided to provide a means for the end users to define their own indicators or modify the existing ones using a new scripting language called Indicator Scripting Language or ISL.
Generally speaking, ISL enables a user to define an indicator, which can be thought of a “class” as in object-oriented programming languages such as Java or C++. We adopted the Java policy of “one public class definition per source file”, and hence one ISL source file can contain definition of one indicator only, since an indicator is always “public” in nature. A source file is shareable among multiple users and is easily deployable in the system – a feature which gave the traders the tremendous freedom to write their own indicators and share/sell them to their peers!
Our next design consideration was to make the language fully object-oriented. By “object-oriented”, we mean real “object-oriented”. That means, we had to support all those things we studied at our computer science classes – polymorphism, inheritance, etc.
Before we go into the details of the design, let’s discuss about the anatomy of an indicator! Each indicator can have one or more series as shown by two arrows in the diagram below. A series is basically a set of values plotted over a range of time.
How a series will be drawn (that is, its shape and curvature) is governed by a series-processing function and optionally by some properties. Thus, an indicator consists of at least one series (there can be more), at least one series-processing function (there can be more if there are multiple series), zero or more general functions, and zero or more properties.
A function holds the actual processing code. As mentioned above, a series must have a series processing function (AKA main function, analogous to traditional programming languages) to process the data:
y = f(t) where t represents the real-time time axis data. A main function can be broken down to several smaller functions to make the code modular enabling one function to call another, again just like in traditional programming languages. Our design consideration included support for recursion as well!
The syntax and semantics of an ISL function is very similar to an ActionScript function (or a Javascript function) – which has syntax not very strongly-typed and not very loosely-typed either!
A property can be thought of as a variable holding a value. We kept support for all standard data types, such as string, numeric, boolean, date-time and even some advanced ones, such as ARGB color.
From the very beginning, we wanted to make sure that ISL ensures code reuse. We designed it in a way so that an indicator can reuse code from the other pre-written indicators through partial inheritance, full inheritance and multiple inheritance. Not only a function can be overridden, a series or a property can be overridden as well.
Following is the final architectural diagram of an indicator:
The diagram shows another entity that we didn’t discuss earlier called shapes, which is an advanced feature of ISL and is out of scope of this discussion. In short, we implemented a shape rendering engine in Sycap Chart that deals with generating, rendering and controlling shapes of any type. ISL lets a user to draw custom shapes through scripting as well. We hope to discuss more about it in detail some time in future.
From our above discussion, it is very much understandable that an indicator source file contains 4 blocks of code – properties, functions, series and the indicator itself. One of the major challenges for us was to come up with the structure of an ISL source file (AKA an indicator file) – its elements, their syntax and semantics and the interaction between the elements. We had to develop syntaxes which shouldn’t become tough for non-programmers but should have enough firepower to allow users to write the most complex indicator possible.
Shown below is what we call a “Hello World” indicator script. It basically does nothing but demonstrates the structure of an ISL program.
Property steps { Type = Numeric; Description = Steps; Label = Steps; DefaultValue = 10; } Property lineColor { Type = Color; Description = Color; Label = Color; DefaultValue = 0xFF0000; } Function seriesFunc(chartDataCollection:Array, properties:Array) { var dataSet:ChartData = chartDataCollection[0]; var result : Number = 0; for(var i : Number = 0; i < dataSet.Data.length; i++) result += dataSet.Data[i].close; return result / dataSet.Data.length; } Series series { Type = LineChart; Visible = true; LineColor = Eval( lineColor ); Panel = 0; DataStreamCount = 1; Function = SMAIndicator_seriesFunc; } Indicator SMAIndicator { Name = SMA Indicator; Series = [series]; Description = SMA Indicator; }
Once we were done designing the structural layout of the scripting language, our next challenge was to implement a lightning-fast interpreter for it. The interpreter had to perform really fast because of the real-time nature of our application, and the processing overhead of ISL needed to be as negligible as possible.
We look forward to discussing the implementation aspects of ISL and its interpreter on our next article which is coming soon. So stay tuned folks!