Topic: Help wanted - coding simple indicator (I originally coded in MT4)

Hi,

I have a simple indicator that I coded for MT4 and have tried using Visual C# to code for FSB. The indicator is a line indicator on the main chart and looks like an MA.

I've used the MA code as a basis, and when loading into FSB I get the following message:

Error when executing Calculate(SlotTypes.NotDefined). Index was outside the bounds of the array.

I've copied the core logic from my MT4 vesrion below.

Appreciate any help/comments

//----
   for (curbar=limit;curbar>=0;curbar--)
     {
           
      if (Close[curbar]==StopLossBuffer[curbar+1]) StopLossBuffer[curbar] = StopLossBuffer[curbar+1];
     
      else if (Close[curbar+1]<=StopLossBuffer[curbar+1] && Close[curbar]<StopLossBuffer[curbar+1])
           StopLossBuffer[curbar]=MathMin(StopLossBuffer[curbar+1],Close[curbar]+StopLoss);
           
      else if (Close[curbar+1]>=StopLossBuffer[curbar+1] && Close[curbar]>StopLossBuffer[curbar+1])
           StopLossBuffer[curbar]=MathMax(StopLossBuffer[curbar+1],Close[curbar]-StopLoss);
           
      else if (Close[curbar]>StopLossBuffer[curbar+1]) StopLossBuffer[curbar]=MathMax(StopLossBuffer[curbar+1],Close[curbar]-StopLoss);
     
      else StopLossBuffer[curbar]=MathMin(StopLossBuffer[curbar+1],Close[curbar]+StopLoss);

Re: Help wanted - coding simple indicator (I originally coded in MT4)

Hi Barno,
if you're using Visual Studio, just wanted to mention first you can download the FSB source, then develop your indicator in the FSB folder. It will do all the debugging and error catching for you, and helps with the autocompletes.
Source on github:
https://github.com/PopovMP/Forex-Strategy-Builder
you might have to read through their manual about registering and downloading a fork to your local machine. There might be a zip file of the source somewhere too for easy download and setup.

Then, for debugging your indicator, add it to your FSB project, described here:
http://forexsb.com/forum/post/11374/#p11374
It's just adding one line in one of the source files then running the project.

For your indicator, any of the price series arrays refer to that bar in your entire dataset, not the bar in the lookback period. If curbar goes to 0, then
curbar = 0
Close[curbar]
will get the the closing price from the first bar of your data file.

"Bars" is the total number of bars in your dataset; I usually have 4 months of 5 minute data, so comes to around 25,000. The usual convention on most indicators is to iterate forward through all the bars, then do some calculation over the lookback. Usually the iterator is "iBar", and the start is "iFirstBar", which is set to some value greater than the lookback periods of the parameters to avoid "Index Out of Bounds" error.

2 possibilities:
1)
Do you know if it's Close[curbar], Close[curbar+1], StopLossBuffer[curbar], or StopLossBuffer[curbar+1]?
If it's Close[curbar+1], probably trying to access a bar jsut out of the data set.
If it's StopLossBuffer, be sure StopLossBuffer is created with a sufficient size, usually size of Bars.
If it's StopLossBuffer[curbar+1], same as trying to access a bar just outside of the dataset.

First guess -- limit may be set to Bars or Bars-1, then [curbar+1] would be outside the dataset. If [curbar+1] is greater than [Bars-1], it will throw the index out of range error.
On the other side, limit may somehow decrease to -1.

You might have to change the >= to > to get the number of bars right, or change "curbar=limit" to "curbar=limit-1". If you want 10 bars in your lookback, and limit is set to 10, the for loop as coded above will get 11 bars. I usually have to try a few things to get the number correct.

2)
For your indicator, try something like this:

int limit = (int)IndParam.NumParam[0].Value;   // could be [0] to [5]

int iFirstBar = limit + 5;    // could be 5 or anything, just advances past the first few bars

for (int iBar = iFirstBar; iBar < Bars; iBar++) {
    for (curbar=limit;curbar>=0;curbar--) {
        Close[iBar-curbar] = ....

Then iBar advances through all the bars, then curbar in the inner loop gets the values from the lookback period. With this style, you might have to change the >= to > to get the number of bars right, or change "curbar=limit" to "curbar=limit-1". In porting MT4 indicators, I usually have to try a few adjusting tricks like that to get the values to sync up correctly. I usually do it the other way (    (int curbar=0; curbar < limit; curbar++)  Close[iBar-curbar]   ) but it's not a real reason, that's just the style I learned.

Hope that helps, I'd be happy to hear how it goes.

Re: Help wanted - coding simple indicator (I originally coded in MT4)

Your coding in C# would be more helpful I think. Probably iFirstBar is not correctly set, but there maybe other reasons. Below is my example how would I code it in C# but bear in mind I'm learning coding from my own mistakes, from Krog tips and teachings and from code examples in general - that is I'm not an expert wink

 for (curbar=iFirstBar;curbar <Bars;curbar++)
     {
           
      if (Close[curbar]==StopLossBuffer[curbar-1]) StopLossBuffer[curbar] = StopLossBuffer[curbar-1];
     
      else if (Close[curbar-1]<=StopLossBuffer[curbar-1] && Close[curbar]<StopLossBuffer[curbar-1])
           StopLossBuffer[curbar]=Math.Min(StopLossBuffer[curbar-1],Close[curbar]+StopLoss);
           
      else if (Close[curbar-1]>=StopLossBuffer[curbar-1] && Close[curbar]>StopLossBuffer[curbar-1])
           StopLossBuffer[curbar]=MathMax(StopLossBuffer[curbar-1],Close[curbar]-StopLoss);
           
      else if (Close[curbar]>StopLossBuffer[curbar-1]) StopLossBuffer[curbar]=Math.Max(StopLossBuffer[curbar-1],Close[curbar]-StopLoss);
     
      else StopLossBuffer[curbar]=Math.Min(StopLossBuffer[curbar-1],Close[curbar]+StopLoss);

Re: Help wanted - coding simple indicator (I originally coded in MT4)

Oh, Krog beat me big_smile

Re: Help wanted - coding simple indicator (I originally coded in MT4)

Hi Krog/Footon,

The limit variable in my MT4 was just set at 10 (arbitary) ensuring that the initial calculation didn't start at the very 1st bar in my dataset, and in FSB is linked to the iFirstBar.

To provide some context to my indicator

1) it's a sort of SAR type indicator (I've called it adSAR)
2) if the recent high = 100 and iDelta value is set to 5,  adSAR would be 100-5 =95
3) adSAR will remain at 95 until price either went above 100 or below 90
   e.g. if price = 105,adSAr will rise to 100
         if price = 85 , adSAr would fall 90
4) cycle continues 


The following is my calculation code and will hopefully make it easier to understand (alpologies should have included this in my 1st post) :

// Reading the parameters
            BasePrice price = (BasePrice)IndParam.ListParam[1].Index;
            int iShift = (int)IndParam.NumParam[1].Value;
            int iDelta = (int)IndParam.NumParam[0].Value;
            int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0;

            // TimeExecution
            if (price == BasePrice.Open && iShift == 0)
                IndParam.ExecutionTime = ExecutionTime.AtBarOpening;

            // Calculation
            double[] adSAR = new double[Bars];
            int iFirstBar = Bars - 10;

            for (int iBar = iFirstBar; iBar < Bars; iBar++)
            {
                if (Close[iBar] == adSAR[iBar - 1]) adSAR[iBar] = adSAR[iBar - 1];

                else if (Close[iBar - 1] <= adSAR[iBar - 1] && Close[iBar] < adSAR[iBar - 1])
                    adSAR[iBar] = Math.Min(adSAR[iBar - 1], Close[iBar] - iDelta);

                else if (Close[iBar - 1] >= adSAR[iBar - 1] && Close[iBar] > adSAR[iBar - 1])
                    adSAR[iBar] = Math.Max(adSAR[iBar - 1], Close[iBar] + iDelta);

                else if (Close[iBar] > adSAR[iBar - 1]) adSAR[iBar] = Math.Max(adSAR[iBar - 1], Close[iBar] + iDelta);

                else adSAR[iBar] = Math.Min(adSAR[iBar - 1], Close[iBar] - iDelta);
            }

Regards

Paul

Re: Help wanted - coding simple indicator (I originally coded in MT4)

I can see this is not right:

int iFirstBar = Bars - 10; 

Leave it as 10:

int iFirstBar = 10 +iShift+iDelta; 

Mql counts bars from right to left, FSB counts from left to right.

Re: Help wanted - coding simple indicator (I originally coded in MT4)

Hi Footon,

Thx for the advise re: iFirstbar setting. Have applied this to no avail. Tried a couple of things - again no progress

I've hopefully added my CS file -perhaps it will help a little more, and as I said in my earlier post, I've modelled on MA indicator.

I started with simple copy, then renamed my varibales over the MA, and confirmed it was ok in FSB, then started stripping unwanted code, but again retaining the MA calc, again ok in FSB, and it's only when I've  started to work on my own calc detailss that I now find the array error.

Any assistance greatly appreciated

Regards

Paul.

Re: Help wanted - coding simple indicator (I originally coded in MT4)

Sorry - should also have added in response to Krug, that I tried adding the additional  -  for (iBar=iFirstBar;iBar>=0;iBar--) - but again to no avail.

I'm guessing that I'll really kick myself once we get to the bottom of it, but only way to learn.

Really appreciate help you given so far - has at leaast encourage me to look at other avenues.

Paul.

Re: Help wanted - coding simple indicator (I originally coded in MT4)

barno wrote:

Sorry - should also have added in response to Krug, that I tried adding the additional  -  for (iBar=iFirstBar;iBar>=0;iBar--) - but again to no avail.

I'm guessing that I'll really kick myself once we get to the bottom of it, but only way to learn.

Really appreciate help you given so far - has at leaast encourage me to look at other avenues.

Paul.

Hi Paul,
I thought the first post was FSB C# code, but then noticed that was MT4 C++ code, oh no, sorry my mistake. Unfortunately, attachments aren't working on the forum.

For the current, one, I'd recommend stick with
for (int iBar = iFirstBar; iBar < Bars; iBar++)
{
instead of
for (iBar=iFirstBar;iBar>=0;iBar--)

Everything looks right, I pasted in your calculation code, could not get the error, here are some more details to check:

1) you may have more Components at the bottom than set in the Components[] initialization.
How to test: comment out everything inside the for loop with /*   ... */, see if you still get error
At the bottom, it has "Component = new IndicatorComp[2];", but the size changes depending on if its Open, OpenFilter, or Close / Close Filter. This could happen if you copied and pasted in another Component block for showing more info.

2) if 2) does not throw error, then verify iDelta, iShift, iFirstBar, and Bars give good values.
Try the message box approach, before the for loop, it will quickly show if one of them is NaN, or a large negative number, or something unexpected. It looks like they should be between 0 and 15 or so.

3) verify: BasePrice price = (BasePrice)IndParam.ListParam[1].Index; is the parameter above with the base price setting, not the smoothing method. But this is low probability, I don't think it would throw the error.

let me know what you find, I'm interested to figure this out

Re: Help wanted - coding simple indicator (I originally coded in MT4)

At the moment attachments not working in here, sorry for that. You could post the entire code using the code button just above the text box.

Have you added another component?

Re: Help wanted - coding simple indicator (I originally coded in MT4)

Krog beat me again  smile

Re: Help wanted - coding simple indicator (I originally coded in MT4)

Hi Krog / Footon,

Managed to get the indicator looking like it should , and as suggested, the error was created by my cribbing other indicator code and not aligning the components.

Resolved the issue by starting with the Parabolic SAR code (rather than MA) and putting in my own calculations (also managed to cut lines of calc code down). Also realised that I had to apply "Point" to my iDelta value.

Thanks for your help - gives me a good start point looking at the Slottype elements of the indicator.

The basics of the startegy / indicator are:

1) check for iBar opening below/close above adSAR[iBar-1]
2) Go long during the new bar e.g. [iBar+1], but add spread + 1 pip to the close of the iBAR which crossed the adSAR.
3) set inital stoploss of adSAR - iDelta & take profit at set value.


This is the start point for stargtegy, after which I'll look to apply more detailed criteria to atempt to eliminae false starts / whipsaws etc.

// Barnov SAR Indicator


using System;
using System.Drawing;

namespace Forex_Strategy_Builder
{
    /// <summary>
    /// Barnov SAR Indicator
    /// </summary>
    public class Barnov_SAR2 : Indicator
    {
        /// <summary>
        /// Sets the default indicator parameters for the designated slot type
        /// </summary>
        public Barnov_SAR2(SlotTypes slotType)
        {
            // General properties
            IndicatorName = "Barnov SAR2";
            PossibleSlots = SlotTypes.OpenFilter;

            // Setting up the indicator parameters
            IndParam = new IndicatorParam();
            IndParam.IndicatorName = IndicatorName;
            IndParam.SlotType = slotType;
            CustomIndicator = true;

            // The ComboBox parameters
            IndParam.ListParam[0].Caption = "Logic";
            if (slotType == SlotTypes.OpenFilter)
                IndParam.ListParam[0].ItemList = new string[] 
                {
                    "The price is higher than the PSAR value" 
                };
            else
                IndParam.ListParam[0].ItemList = new string[]
                {
                    "Not Defined"
                };
            IndParam.ListParam[0].Index = 0;
            IndParam.ListParam[0].Text = IndParam.ListParam[0].ItemList[IndParam.ListParam[0].Index];
            IndParam.ListParam[0].Enabled = true;
            IndParam.ListParam[0].ToolTip = "Logic of application of the indicator.";

            // The NumericUpDown parameters
            IndParam.NumParam[0].Caption = "Delta";
            IndParam.NumParam[0].Value = 500;
            IndParam.NumParam[0].Min = 1;
            IndParam.NumParam[0].Max = 999;
            IndParam.NumParam[0].Enabled = true;
            IndParam.NumParam[0].ToolTip = "The Barnov SAR Delta.";

            return;
        }

        /// <summary>
        /// Calculates the indicator's components
        /// </summary>
        public override void Calculate(SlotTypes slotType)
        {
            // Reading the parameters
            double iDelta = (int)IndParam.NumParam[0].Value * Point;
            int iPrvs = IndParam.CheckParam[0].Checked ? 1 : 0;


            // Calculation
            double[] adSAR = new double[Bars];
            int iFirstBar = 10 + iPrvs;
            adSAR[0] = 0;

            for (int iBar = iFirstBar; iBar < Bars; iBar++)
            {

                if (Close[iBar] == adSAR[iBar - 1]) adSAR[iBar] = adSAR[iBar - 1];

                else if (Close[iBar] < adSAR[iBar - 1]) adSAR[iBar] = Math.Min(adSAR[iBar - 1], Close[iBar] + iDelta);

                else  adSAR[iBar] = Math.Max(adSAR[iBar - 1], Close[iBar] - iDelta);

                

            }
            // Saving the components
            Component = new IndicatorComp[1];

            Component[0] = new IndicatorComp();
            Component[0].CompName = "SAR Value";
            Component[0].DataType = IndComponentType.IndicatorValue;
            Component[0].ChartType = IndChartType.Line;
            Component[0].ChartColor = Color.Red;
            Component[0].FirstBar = iFirstBar;
            Component[0].Value = adSAR;

            return;
        }

        /// <summary>
        /// Sets the indicator logic description
        /// </summary>
        public override void SetDescription(SlotTypes slotType)
        {
            EntryFilterLongDescription = "the price is higher than the " + ToString();
            EntryFilterShortDescription = "the price is lower than the " + ToString();
            ExitPointLongDescription = "at the " + ToString() + ". It determines the position direction also";
            ExitPointShortDescription = "at the " + ToString() + ". It determines the position direction also";

            return;
        }

        /// <summary>
        /// Indicator to string
        /// </summary>
        public override string ToString()
        {
            string sString = IndicatorName + " (" +
                IndParam.NumParam[0].ValueToString + ")";   // Delta
            return sString;
        }
    }
}

 


Regards

Paul.

Re: Help wanted - coding simple indicator (I originally coded in MT4)

Glad to hear it worked out. To make more components, change
Component = new IndicatorComp[1];
replace [1] with however many components you need. I usually have 6, one for the indicator, the other 5 for tracing values for coding.
At some point, you might need to use iPrvs if entering at a specific price level, best used with SlotType.Open.
This is great, and I am happy to help out if I can.