Reference Custom Library using .dll throw nullreference

Created at 14 Aug 2018, 19:54
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
MY

myinvestmentsfx

Joined 06.11.2017

Reference Custom Library using .dll throw nullreference
14 Aug 2018, 19:54


Hi Guys,

Some help, i'm building a custom library with multiple classes (BotBuildingBlocks) & (IndicatorBuildingBlocks)

Custom Class -> MGTradingLibrary.dll with below BotBuildingBlocks class.  Inheriting Robot class.

using System;
using System.Diagnostics;
using System.Linq;
using cAlgo.API;
using System.Collections.Generic;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Threading;

namespace MGTradingLibrary
{
    /// <summary>
    /// This class is a collection of methods that can be used when building a Bot.
    /// </summary>
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class BotBuildingBlocks : Robot
    {
        /// <summary>
        /// Summary: This method checks if the current time is within the user-defined trading window. 
        /// <para> Detail: 1. Timezone is South African Standard Time --- 2. Automatically adjusts for daylight savings --- 3. Will return a string 'Trading Window Active or Trading Window Not Active' </para>
        /// </summary>
        /// <param name="startTime">Enter the start of the trading window in hours.</param>
        /// <param name="stopTime">Enter the end of the trading window in hours.</param>
        public string zzzActiveTradingWindow(double startTime, double stopTime)
        {
            string tradingWindowActive = "Trading Window Not Active";
            try
            {
                bool isDST = Server.Time.IsDaylightSavingTime();
                double currentTime = Server.Time.Hour;
                
                if (isDST)
                {
                    startTime = startTime + 1;
                    stopTime = stopTime + 1;
                }
                if (currentTime > startTime && currentTime < stopTime)
                    return tradingWindowActive = "Trading Window Active";
                else
                {
                    Print("Trading Window Active, Time is ", Server.Time);
                    return tradingWindowActive;
                }

            }
            catch (Exception error)
            {
                Print("zzzActiveTradingWindow Method Error: ", error.ToString());
                return (error.ToString());
            }
        }
        /// <summary>
        /// Summary: This method will collect all the Swing High points.
        /// <para> Detail: 1. Will return an x amount of Swign Highs contained in a list of doubles </para>
        /// </summary>
        /// <param name="candleCount">The amount of candles before and after the high before classifying it as a Swing High.</param>
        /// <param name="timeFrame">Select the timeframe you want to calculate Swing Highs on.</param>
        /// <param name="listSize">The amount of swing highs you want to store in the list.</param>
        public List<double> zzzSwingHighs(int candleCount, int listSize, TimeFrame timeFrame)
        {
            List<double> swingHighs = new List<double>();
            try
            {
                int period = candleCount % 2 == 0 ? candleCount - 1 : candleCount;
                

                for (int bar = 0; bar < MarketData.GetSeries(Symbol, timeFrame).High.Count; bar++)
                {
                    int middleIndexHigh = bar - period / 2;
                    double middleValueHigh = MarketData.GetSeries(Symbol, timeFrame).High[middleIndexHigh];
                    bool up = true;

                    for (int i = 0; i < period; i++)
                    {
                        if ((middleValueHigh < MarketData.GetSeries(Symbol, timeFrame).High[bar - i]))
                        {
                            up = false;
                            break;
                        }
                    }
                    if (up)
                    {
                        swingHighs.Add(middleValueHigh);

                        if (swingHighs.Count > listSize)
                            swingHighs.RemoveAt(0);
                    }
                }
                return swingHighs;
            }
            catch (Exception error)
            {
                Print("Swing High Method Error: ", error.ToString());
                return swingHighs;
            }
        }
        /// <summary>
        /// Summary: This method will collect all the Swing Low points.
        /// <para> Detail: 1. Will return an x amount of Swign Lows contained in a list of doubles </para>
        /// </summary>
        /// <param name="candleCount">The amount of candles before and after the high before classifying it as a Swing High.</param>
        /// <param name="timeFrame">Select the timeframe you want to calculate Swing Highs on.</param>
        /// <param name="listSize">The amount of swing highs you want to store in the list.</param>
        public List<double> zzzSwingLows(int candleCount, int listSize, TimeFrame timeFrame)
        {
            List<double> swingLows = new List<double>();
            try
            {
                int period = candleCount % 2 == 0 ? candleCount - 1 : candleCount;

                for (int bar = 0; bar < MarketData.GetSeries(Symbol, timeFrame).Low.Count; bar++)
                {
                    int middleIndexLow = bar - period / 2;
                    double middleValueLow = MarketData.GetSeries(Symbol, timeFrame).Low[middleIndexLow];
                    bool down = true;

                    for (int i = 0; i < period; i++)
                    {
                        if ((middleValueLow < MarketData.GetSeries(Symbol, timeFrame).Low[bar - i]))
                        {
                            down = false;
                            break;
                        }
                    }
                    if (down)
                    {
                        swingLows.Add(middleValueLow);

                        if (swingLows.Count > listSize)
                            swingLows.RemoveAt(0);
                    }
                }
                return swingLows;
            }
            catch (Exception error)
            {
                Print("Swing High Method Error: ", error.ToString());
                return swingLows;
            }



    }

When reference the class with the using statement as per below. 

---.Net Frameworks are the same

---Everything builds

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using MGTradingLibrary;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MethodTester : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        protected override void OnStart()
        {
            Test();
        }

        protected override void OnTick()
        {
            // Put your core logic here
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
        public void Test()
        {
            BotBuildingBlocks test = new BotBuildingBlocks();
            var output = test.zzzSwingHighs(5, 5, TimeFrame.Daily);

        }
    }
}

it crashes OnStart with NullReferenceException.  Does anyone perhpas know why?


@myinvestmentsfx
Replies

.ics
15 Aug 2018, 02:09

Did you make a reference to the .dll file?

Open your algo in automate > at top center, Manage References > Libraries > Browse to your .dll and check it > Apply > rebuild your algo and retry.

Grtz.


@.ics

myinvestmentsfx
15 Aug 2018, 07:48

Hi .ics,

Library is referenced in the manner you explained, still getting nullreference.

Kind Regards,


@myinvestmentsfx

myinvestmentsfx
15 Aug 2018, 14:20

So for those who are interested.  This issue was that my "BuildingBlocks" class was inheriting the cAlgo "Robot" class and then when I built the "Run" class it was set to inherit the same "Robot" class.  I think changed my "Run" class to inherit my custom "BuildingBlocks" class, which in the backend inherits the "Robot" class.

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Diagnostics;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Threading;
using MGTradingLibrary;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Run : BotBuildingBlocks
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        protected override void OnStart()
        {

        }

        protected override void OnTick()
        {
            // Put your core logic here
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
        public void Test()
        {
            var test = zzzActiveTradingWindow(2, 3);

        }

    }

}

 


@myinvestmentsfx