This tutorial will show you an advanced example for indicators, conditions, strategies and give you the ability to communicate between these scripts. This will lead you to more code transparency and reduces your programming time.
Why do we want this?
AgenaTrader provides you the ability to create indicators, conditions, alerts and strategies in c# and use them during trading. Of course, you can start creating an indicator and copy the code afterwards into a condition, a strategy or an alert. Programming by using “copy & paste” is easy but on the other hand there are many disadvantages like lack of testing reasons, no single point for bug fixing and low maintainability.
Indicator
In many cases we are starting with indicators because indicators are the easiest place to start on script development. You will get a quick indication if your trading idea is working and addionally you can screen your instruments of choice visually and verify if your trading idea will be profitable.
Result value
The “ResultValue” object will hold all result data from the “calculate” method. Based on this result data, the next steps will be determined. In a strategy we create long or short orders, in a condition we set the “Occured” object, and so on. In our example, we use our global “ResultValue” object, of course you can use your own class if you need more properties.
[pastacode lang=”java” manual=”public%20class%20ResultValue_Example_Indicator_SMA_CrossOver_Advanced%0A%7B%0A%20%20%20%20public%20bool%20ErrorOccured%20%3D%20false%3B%0A%20%20%20%20public%20OrderAction%3F%20Entry%20%3D%20null%3B%0A%20%20%20%20public%20OrderAction%3F%20Exit%20%3D%20null%3B%0A%20%20%20%20public%20double%20Price%20%3D%200.0%3B%0A%20%20%20%20public%20double%20Slow%20%3D%200.0%3B%0A%20%20%20%20public%20double%20Fast%20%3D%200.0%3B%0A%7D” message=”” highlight=”” provider=”manual”/]
Method calculate
We want to encapsulate the main logic into one main method in the indicator. In our case we do this by using the following public method in the indicator.
[pastacode lang=”java” manual=”public%20ResultValue_Example_Indicator_SMA_CrossOver_Advanced%20calculate(IDataSeries%20data%2C%20int%20fastsma%2C%20int%20slowsma%2C%20bool%20islongenabled%2C%20bool%20isshortenabled)%20%7B%0A%2F*%0A*%20Here%20we%20do%20all%20the%20smart%20work%20and%20in%20the%20end%20we%20return%20our%20result%20object.%0A*%20So%20the%20calling%20scripts%20knows%20what%20to%20do%20(e.g.%20a%20strategy%20will%20create%20an%20order%20in%20the%20market%2C%20the%20condition%20will%20create%20a%20signal%2C%20and%20so%20on).%0A*%2F%0A%7D” message=”” highlight=”” provider=”manual”/]
So it is possible that other scripts just call the “calculate” method of the indicator and get a decision of what to do. In our case the “calculate” method returns an object which holds all important information what has to be done. If we get the “OrderAction.Buy” as an “Entry” result, we need to start a long order in a strategy or we set the condition value to 1.
Condition
As we have finished our indicator, we can start working on our condition. Because we already have added our trading concept in the “calculate” method in the indicator, we just need a reference to our indicator and we are almost done.
[pastacode lang=”java” manual=”private%20Example_Indicator_SMA_CrossOver_Advanced%20_Example_Indicator_SMA_CrossOver_Advanced%20%3D%20null%3B%0A” message=”” highlight=”” provider=”manual”/]
We need to initalize this variable in our OnStartUp() method:
[pastacode lang=”java” manual=”protected%20override%20void%20OnStartUp()%0A%7B%0A%20%20%20%20%20base.OnStartUp()%3B%0A%0A%20%20%20%20%20%2F%2FInit%20our%20indicator%20to%20get%20code%20access%20to%20the%20calculate%20method%0A%20%20%20%20%20this._Example_Indicator_SMA_CrossOver_Advanced%20%3D%20new%20Example_Indicator_SMA_CrossOver_Advanced()%3B%0A%7D” message=”” highlight=”” provider=”manual”/]
Now we are ready to use the “calculate” method of the indicator in our OnBarUpdate() method of the condition:
[pastacode lang=”java” manual=”%2F%2FLets%20call%20the%20calculate%20method%20and%20save%20the%20result%20with%20the%20trade%20action%0AResultValue_Example_Indicator_SMA_CrossOver_Advanced%20returnvalue%20%3D%20this._Example_Indicator_SMA_CrossOver_Advanced.calculate(this.Input%2C%20this.FastSma%2C%20this.SlowSma%2C%20this.IsLongEnabled%2C%20this.IsShortEnabled)%3B” message=”” highlight=”” provider=”manual”/]
In the code snippet above we see that the return value of the “calculate” method is our “ResultValue” from the beginning of this tutorial. So we just need to evaluate this object.
[pastacode lang=”java” manual=”%2F%2FEntry%0Aif%20(returnvalue.Entry.HasValue)%0A%7B%0A%20%20%20switch%20(returnvalue.Entry)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20case%20OrderAction.Buy%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2FLong%20Signal%0A%20%20%20%20%20%20%20%20%20%20%20%20Occurred.Set(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Entry.Set(1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20case%20OrderAction.SellShort%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%2F%2FShort%20Signal%0A%20%20%20%20%20%20%20%20%20%20%20%20Occurred.Set(-1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Entry.Set(-1)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%7D%0A%7D%0Aelse%0A%7B%0A%20%20%20%2F%2FNo%20Signal%0A%20%20%20Occurred.Set(0)%3B%0A%20%20%20Entry.Set(0)%3B%0A%7D” message=”” highlight=”” provider=”manual”/]
Strategy
Of course we are following the same procedure as in our condition. We create a variable of the indicator class, we initalize this variable during the OnStartUp() method and we use the object in our OnBarUpdate() method. Please pay attention while backtesting with the parameter “Orders Handling Mode = Advanced”, in this case we need at least two bars!
[pastacode lang=”java” manual=”%2F%2FBecause%20of%20backtesting%20reasons%20if%20we%20use%20the%20advanced%20mode%20we%20need%20at%20least%20two%20bars!%0A%2F%2FIn%20this%20case%20we%20are%20using%20SMA50%2C%20so%20we%20need%20at%20least%2050%20bars.%0Athis.BarsRequired%20%3D%2050%3B” message=”” highlight=”” provider=”manual”/]
If you start the strategy on a chart the TimeFrame is automatically set. If you start this strategy within the “Strategy Escort”, it would be a smart idea to set a default TimeFrame, this will lead to a better usability. We do this by adding the default TimeFrame in the Initialize() method.
[pastacode lang=”java” manual=”if%20(this.TimeFrame%20%3D%3D%20null%20%7C%7C%20this.TimeFrame.PeriodicityValue%20%3D%3D%200)%0A%7B%0A%20%20%20%20this.TimeFrame%20%3D%20new%20TimeFrame(DatafeedHistoryPeriodicity.Day%2C%201)%3B%0A%7D” message=”” highlight=”” provider=”manual”/]
We use IsAutomated = true to decide if the strategy will do all work fully automated. In this case the strategy can be used within the “Strategy Escort” and will create entry & exit orders automatically.
In the end of the strategy file there are four methods: DoEnterLong(), DoEnterShort(), DoExitLong() and DoExitShort() In these methods we implement all rules for the creation of orders.
Miscellaneous
Filenames and Class names
To import all scripts into AgenaTrader without any error we add “_indicator”, “_strategy”, “_condition” or “_alert” to the filename and also to the c# class name. This is important because if you like to use all files in your AgenaTrader the names must be different. It is not possible to have an indicator and condition with the same name, e.g. “SMA_CrossOver”. They must have unique names like “SMA_CrossOver_indicator” and “SMA_CrossOver_condition”!
Color and drawing style
If the user has changed the color or the drawing style of the script (indicator or condition) we need to change the setting during the OnBarUpdate() method.
[pastacode lang=”java” manual=”%2F%2FSet%20the%20drawing%20style%2C%20if%20the%20user%20has%20changed%20it.%0APlotColors%5B0%5D%5B0%5D%20%3D%20this.Plot0Color%3B%0APlots%5B0%5D.PenStyle%20%3D%20this.Dash0Style%3B%0APlots%5B0%5D.Pen.Width%20%3D%20this.Plot0Width%3B” message=”” highlight=”” provider=”manual”/]
DisplayName and ToString()
In each script we override the ToString() method and the DisplayName property to provide a readable string in AgenaTrader. So we do see a readable string instead of the class name in AgenaTrader. In parentheses we add and C for Condition, I for Indicator, A for Alert and S for Strategy to ensure that we can distinguish between the scripts (e.g. if we are editing on indicators or conditions in charts).
[pastacode lang=”java” manual=”%2F%2F%2F%20%3Csummary%3E%0A%20%20%20%20%20%20%20%20%2F%2F%2F%20defines%20display%20name%20of%20indicator%20(e.g.%20in%20AgenaTrader%20chart%20window)%0A%20%20%20%20%20%20%20%20%2F%2F%2F%20%3C%2Fsummary%3E%0A%20%20%20%20%20%20%20%20%2F%2F%2F%20%3Creturns%3E%3C%2Freturns%3E%0A%20%20%20%20%20%20%20%20public%20override%20string%20ToString()%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%22Example%20SMA%20CrossOver%20Advanced%20(I)%22%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%2F%2F%2F%20%3Csummary%3E%0A%20%20%20%20%20%20%20%20%2F%2F%2F%20defines%20display%20name%20of%20indicator%20(e.g.%20in%20AgenaTrader%20indicator%20selection%20window)%0A%20%20%20%20%20%20%20%20%2F%2F%2F%20%3C%2Fsummary%3E%0A%20%20%20%20%20%20%20%20public%20override%20string%20DisplayName%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20get%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%22Example%20SMA%20CrossOver%20Advanced%20(I)%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D” message=”” highlight=”” provider=”manual”/]