NullReferenceException thrown when injecting dependency in class constructor with Symbol as parameter

Created at 05 Aug 2020, 13:24
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!
GA

galaaoui.salma

Joined 23.07.2020

NullReferenceException thrown when injecting dependency in class constructor with Symbol as parameter
05 Aug 2020, 13:24


Hello,

I'm trying to work on a cBot that treats multiple currency pairs and tries to extract different data (Bid, Ask, DOM) among other things for each currency, I've implemented a CurrencyPair class whose constructor takes a Symbol interface as a parameter and assigns it to a class field of type Symbol in order to use the properties bid, ask, name.. The cBot builds successfully but as soon as I run it, it throws a NullReferenceException and the problem seems to originate from the first invocation of a property of the Symbol interface from within the CurrencyPair class. Here is a part of the code:

 

using System;
using System.Collections.Generic;
using System.Threading;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo.Robots
{

    public class CurrencyPair : Robot
    {
        public Symbol _symbol;
        public Dictionary<double, double> BUY = new Dictionary<double, double>();
        public Dictionary<double, double> SELL = new Dictionary<double, double>();
(...)

        public CurrencyPair(Symbol sym)
        {
            _symbol = sym;
        }

        public void StartCurrency()
        {
            _marketDepth = MarketData.GetMarketDepth(_symbol.Name); //problem here
            _marketDepth.Updated += MarketDepthUpdated;
        }

(...)


        public void MarketDepthUpdated()
        {

            Print("Started Event MarketDepthUpdated");

            _marketDepth = MarketData.GetMarketDepth(_symbol.Name);

            curBSpot = _symbol.Bid;
            curASpot = _symbol.Ask;

            SELL.Clear();
            BUY.Clear();

            foreach (var entry in _marketDepth.AskEntries)
                SELL.Add(entry.Price, entry.VolumeInUnits);

            foreach (var entry in _marketDepth.BidEntries)
                BUY.Add(entry.Price, entry.VolumeInUnits);


            prevBSpot = _symbol.Bid;
            prevASpot = _symbol.Ask;

            Print("Exited Event MarketDepthUpdated");
        }

    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Playing_DoM_Sequential : Robot
    {
        protected override void OnStart()
        {
            CurrencyPair EURUSD = new CurrencyPair(Symbols.GetSymbol("EURUSD"));
            EURUSD.StartCurrency(); //problem here

            CurrencyPair GBPUSD = new CurrencyPair(Symbols.GetSymbol("GBPUSD"));

            CurrencyPair EURJPY = new CurrencyPair(Symbols.GetSymbol("EURJPY"));

        }
    }
}

 

What is it that I am doing wrong?


@galaaoui.salma
Replies

PanagiotisCharalampous
05 Aug 2020, 14:13

Hi galaaoui.salma,

Can you please provide the compete cBot code so that we can reproduce this behavior?

Best Regards,

Panagiotis 

Join us on Telegram

 


@PanagiotisCharalampous

galaaoui.salma
05 Aug 2020, 14:46

RE:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo.Robots
{

    public class CurrencyPair : Robot
    {
        public Symbol _symbol;
        public Dictionary<double, double> BUY = new Dictionary<double, double>();
        public Dictionary<double, double> SELL = new Dictionary<double, double>();
        public static Dictionary<KeyValuePair<DateTime, double>, double> BOUGHT = new Dictionary<KeyValuePair<DateTime, double>, double>();
        public static Dictionary<KeyValuePair<DateTime, double>, double> SOLD = new Dictionary<KeyValuePair<DateTime, double>, double>();
        public static double curASpot = 0;
        public static double curBSpot = 0;
        public double prevASpot = 0;
        public double prevBSpot = 0;
        public static double score;
        public static double totAScore;
        public static double totBScore;
        public MarketDepth _marketDepth;


        public CurrencyPair(Symbol sym)
        {
            this._symbol = sym;
        }

        public void StartCurrency()
        {
            _marketDepth = MarketData.GetMarketDepth(_symbol.Name);
            _marketDepth.Updated += MarketDepthUpdated;
        }


        public void MarketDepthUpdated()
        {

            Print("Started Event MarketDepthUpdated");

            _marketDepth = MarketData.GetMarketDepth(_symbol.Name);

            curBSpot = _symbol.Bid;
            curASpot = _symbol.Ask;

            Offset();

            SELL.Clear();
            BUY.Clear();

            foreach (var entry in _marketDepth.AskEntries)
                SELL.Add(entry.Price, entry.VolumeInUnits);

            foreach (var entry in _marketDepth.BidEntries)
                BUY.Add(entry.Price, entry.VolumeInUnits);


            prevBSpot = _symbol.Bid;
            prevASpot = _symbol.Ask;

            Print("Exited Event MarketDepthUpdated");
        }

        public void Offset()
        {

            DateTime now;

            Print("Offset Started");

            if ((prevBSpot == 0) || (prevBSpot == 0) || (curBSpot == 0) || (curASpot == 0))
                return;

            Print(score);


            foreach (var ask in SELL.Reverse())
                if (curASpot >= ask.Key)
                {
                    now = DateTime.UtcNow;
                    BOUGHT.Add(new KeyValuePair<DateTime, double>(now, ask.Key), ask.Value);
                    Print("{0} : BOUGHT : {1}, {2}, {3}", _symbol.Name, now, ask.Key, ask.Value);
                }
                else
                    break;

            foreach (var bid in BUY)
                if (curBSpot <= bid.Key)
                {
                    now = DateTime.UtcNow;
                    SOLD.Add(new KeyValuePair<DateTime, double>(now, bid.Key), bid.Value);
                    Print("{0} : BOUGHT : {1}, {2}, {3}", _symbol.Name, now, bid.Key, bid.Value);
                }
                else
                    break;
        }
    }


    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Playing_DoM_Sequential : Robot
    {
        protected override void OnStart()
        {
            Print("1");
            CurrencyPair EURUSD = new CurrencyPair(Symbols.GetSymbol("EURUSD"));
            EURUSD.StartCurrency();

            Print("2");
            CurrencyPair GBPUSD = new CurrencyPair(Symbols.GetSymbol("GBPUSD"));

            Print("3");
            CurrencyPair EURJPY = new CurrencyPair(Symbols.GetSymbol("EURJPY"));

            Print("4");
        }
    }
}

PanagiotisCharalampous said:

Hi galaaoui.salma,

Can you please provide the compete cBot code so that we can reproduce this behavior?

Best Regards,

Panagiotis 

Join us on Telegram

 

Hi Panagiotis, here you go, the code prints "1" and crashes with NullReferenceException

 


@galaaoui.salma

PanagiotisCharalampous
06 Aug 2020, 08:12

Hi galaaoui.salma,

Your problem lies here

You cannot use MarketData in a robot object that is not attached on a chart. Try passing this object as a parameter to the class.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

galaaoui.salma
06 Aug 2020, 11:44 ( Updated at: 21 Dec 2023, 09:22 )

RE:

PanagiotisCharalampous said:

Hi galaaoui.salma,

Your problem lies here

You cannot use MarketData in a robot object that is not attached on a chart. Try passing this object as a parameter to the class.

Best Regards,

Panagiotis 

Join us on Telegram

Hi Panagiotis, 

The problem isn't only the invocation of GetMarketDepth(Symbol.Name); inside the CurrencyPair projects, passing it as a parameter to the constructor does not solve the issue because the problem is also caused by the subscription to the Updated even inside the class.

Kind Regards,

Salma Galaaoui.


@galaaoui.salma

PanagiotisCharalampous
06 Aug 2020, 11:54

Hi galaaoui.salma,

The root of the problem is the same. You cannot use CurrencyPair.MarketData since it is not initialized anywhere. This property is only initialized when the cBot is attached to a chart.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous