Replies

myinvestmentsfx
17 Dec 2019, 18:10

RE:

PanagiotisCharalampous said:

Hi myinvestmentsfx,

If you need more bars, you can use LoadMoreHistory() method. You can find more information here

Best Regards,

Panagiotis 

Join us on Telegram

 

Sorry for the delay, thank you Panagiotis.  You are always very helpfull :)

 


@myinvestmentsfx

myinvestmentsfx
30 Aug 2018, 18:25

RE:

Panagiotis Charalampous said:

Hi myinvestmentsfx,

If you want to join the points with a line you can use Chart.DrawTrendLine() method. However it is just going to be a collection of straight lines rather than a smoothed line used in the case of an indicator.

Best Regards,

 

Thank you for the reply, I assume should I want this it will be a new feature request? Or I have to just keep it seperate for now.


@myinvestmentsfx

myinvestmentsfx
30 Aug 2018, 14:46 ( Updated at: 21 Dec 2023, 09:20 )

RE:

Panagiotis Charalampous said:

Ηι myinvestmentsfx,

It is not possible to use Output attribute in cBots. If you explain to us more precisely what you are trying to do, we could propose a solution.

Best Regards,

Panagiotis

Hi Panagiotis,

Below you will find the example, where when I create an indicator and run it in the cbot.  I get the value & it draws on the chart even though code is executed in bot.

 

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

namespace MGTradingLibrary
{
    /// <summary>
    /// This class is a collection of methods that can be used when building an Indicator.
    /// </summary>
    [Indicator(AccessRights = AccessRights.FullAccess, AutoRescale = true, IsOverlay = true, ScalePrecision = 5, TimeZone = TimeZones.SouthAfricaStandardTime)]
    public class IndicatorBuildingBlocks : Indicator
    {
        /// <summary>
        /// Summary: This method calculates the swinghigh points based on the MarketSeries.High or MarketSeries.Close property.
        /// <para> Will return IndicatorDataSeries with all the Swing High Points mapped to the appropriate index to plot points on the graph. </para>
        /// </summary>
        /// <param name="symbol">Enter the currency pair you want the calculation done on.</param>
        /// <param name="timeFrame">Enter the timeframe you want the calculation done on.</param>
        /// <param name="candleCount">The amount of candles before and after the high before classifying it as a Swing High.</param>
        /// <param name="swingHighOnGetSeriesClose">If true, it will calculate the Swing Highs based on MarketSeries.Close values, else it will calculate on MarketSeries.High</param>
        /// <param name="iconName">Used if you want to multiple swingHighs for different periods on the same chart. (Auto Drawing on Chart)</param>
        /// <param name="drawSwingHighs">Toggle Auto-Drawing on or off. (Auto Drawing on Chart)</param>
        /// <code>
        /// using MGTradingLibrary; ---- import Library
        /// namespace cAlgo
        ///    {
        ///       [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]  --- Ensure Isoverlay is set to true.
        ///       public class Run : IndicatorBuildingBlocks --- Inherit IndicatorBuildingBlock Class from MGTradingLibrary.
        ///        {
        ///           public override void Calculate(int index)
        ///           {
        ///               zzzGetAndDrawSwingHighs(); --- You can modify default values should you choose to do so.
        ///           }
        ///
        ///       }
        ///   }
        /// </code>
        public IndicatorDataSeries zziGetAndDrawSwingHighs(Symbol symbol = null, TimeFrame timeFrame = null, string iconName = "iconName", int candleCount = 5, bool swingHighOnGetSeriesClose = false, bool drawSwingHighs = true)
        {
            IndicatorDataSeries Result;
            Result = CreateDataSeries();

            if (symbol == null)
                symbol = Symbol;
            if (timeFrame == null)
                timeFrame = TimeFrame;

            try
            {
                MarketSeries getSeriesData = MarketData.GetSeries(symbol, timeFrame);
                int period = candleCount % 2 == 0 ? candleCount - 1 : candleCount;

                if (swingHighOnGetSeriesClose)
                {
                    for (int bar = 0; bar < getSeriesData.Close.Count; bar++)
                    {
                        int middleIndexHigh = bar - period / 2;
                        double middleValueHigh = getSeriesData.Close[middleIndexHigh];
                        bool up = true;

                        for (int i = 0; i < period; i++)
                        {
                            if ((middleValueHigh < getSeriesData.Close[bar - i]))
                            {
                                up = false;
                                break;
                            }
                        }
                        if (up)
                        {
                            Result[middleIndexHigh] = middleValueHigh;
                        }                       
                    }
                }
                else
                {
                    for (int bar = 0; bar < getSeriesData.High.Count; bar++)
                    {
                        int middleIndexHigh = bar - period / 2;
                        double middleValueHigh = getSeriesData.High[middleIndexHigh];
                        bool up = true;

                        for (int i = 0; i < period; i++)
                        {
                            if ((middleValueHigh < getSeriesData.High[bar - i]))
                            {
                                up = false;
                                break;
                            }
                        }
                        if (up)
                        {
                            Result[middleIndexHigh] = middleValueHigh;

                            if(drawSwingHighs)
                            { 
                                var drawSwingHigh = Chart.DrawIcon(iconName + middleIndexHigh.ToString(), ChartIconType.DownArrow, middleIndexHigh, middleValueHigh, Color.Blue);
                            }
                        }
                    }
                }
                return Result;
            }
            catch (Exception error)
            {
                Print("zziGetAndDrawSwingHighs Method Error: ", error.ToString());
                return Result;
            }
        }

I execute method from cBot

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        public IndicatorBuildingBlocks ibb;



        protected override void OnStart()
        {
            ibb = Indicators.GetIndicator<IndicatorBuildingBlocks>();
        }

        protected override void OnTick()
        {
            ibb.zziGetAndDrawSwingHighs();
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

By doing this, I can now Get the data and it will draw it on the chart automatically when calling the method. (See Below).

However, if you want to use the same concept to automatically draw and get the data from the indicator and the indicator is something like an SMA, where you need to draw a line between two points mapped on the chart, the solution on the indicator side is to use Plotype.Line in combination with the Output attribute.  What would you do in this case?  IE is there something that can replace this Plotype.Line functionality.

Thank you for your help.


@myinvestmentsfx

myinvestmentsfx
30 Aug 2018, 14:46 ( Updated at: 21 Dec 2023, 09:20 )

RE:

Panagiotis Charalampous said:

Ηι myinvestmentsfx,

It is not possible to use Output attribute in cBots. If you explain to us more precisely what you are trying to do, we could propose a solution.

Best Regards,

Panagiotis

Hi Panagiotis,

Below you will find the example, where when I create an indicator and run it in the cbot.  I get the value & it draws on the chart even though code is executed in bot.

 

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

namespace MGTradingLibrary
{
    /// <summary>
    /// This class is a collection of methods that can be used when building an Indicator.
    /// </summary>
    [Indicator(AccessRights = AccessRights.FullAccess, AutoRescale = true, IsOverlay = true, ScalePrecision = 5, TimeZone = TimeZones.SouthAfricaStandardTime)]
    public class IndicatorBuildingBlocks : Indicator
    {
        /// <summary>
        /// Summary: This method calculates the swinghigh points based on the MarketSeries.High or MarketSeries.Close property.
        /// <para> Will return IndicatorDataSeries with all the Swing High Points mapped to the appropriate index to plot points on the graph. </para>
        /// </summary>
        /// <param name="symbol">Enter the currency pair you want the calculation done on.</param>
        /// <param name="timeFrame">Enter the timeframe you want the calculation done on.</param>
        /// <param name="candleCount">The amount of candles before and after the high before classifying it as a Swing High.</param>
        /// <param name="swingHighOnGetSeriesClose">If true, it will calculate the Swing Highs based on MarketSeries.Close values, else it will calculate on MarketSeries.High</param>
        /// <param name="iconName">Used if you want to multiple swingHighs for different periods on the same chart. (Auto Drawing on Chart)</param>
        /// <param name="drawSwingHighs">Toggle Auto-Drawing on or off. (Auto Drawing on Chart)</param>
        /// <code>
        /// using MGTradingLibrary; ---- import Library
        /// namespace cAlgo
        ///    {
        ///       [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]  --- Ensure Isoverlay is set to true.
        ///       public class Run : IndicatorBuildingBlocks --- Inherit IndicatorBuildingBlock Class from MGTradingLibrary.
        ///        {
        ///           public override void Calculate(int index)
        ///           {
        ///               zzzGetAndDrawSwingHighs(); --- You can modify default values should you choose to do so.
        ///           }
        ///
        ///       }
        ///   }
        /// </code>
        public IndicatorDataSeries zziGetAndDrawSwingHighs(Symbol symbol = null, TimeFrame timeFrame = null, string iconName = "iconName", int candleCount = 5, bool swingHighOnGetSeriesClose = false, bool drawSwingHighs = true)
        {
            IndicatorDataSeries Result;
            Result = CreateDataSeries();

            if (symbol == null)
                symbol = Symbol;
            if (timeFrame == null)
                timeFrame = TimeFrame;

            try
            {
                MarketSeries getSeriesData = MarketData.GetSeries(symbol, timeFrame);
                int period = candleCount % 2 == 0 ? candleCount - 1 : candleCount;

                if (swingHighOnGetSeriesClose)
                {
                    for (int bar = 0; bar < getSeriesData.Close.Count; bar++)
                    {
                        int middleIndexHigh = bar - period / 2;
                        double middleValueHigh = getSeriesData.Close[middleIndexHigh];
                        bool up = true;

                        for (int i = 0; i < period; i++)
                        {
                            if ((middleValueHigh < getSeriesData.Close[bar - i]))
                            {
                                up = false;
                                break;
                            }
                        }
                        if (up)
                        {
                            Result[middleIndexHigh] = middleValueHigh;
                        }                       
                    }
                }
                else
                {
                    for (int bar = 0; bar < getSeriesData.High.Count; bar++)
                    {
                        int middleIndexHigh = bar - period / 2;
                        double middleValueHigh = getSeriesData.High[middleIndexHigh];
                        bool up = true;

                        for (int i = 0; i < period; i++)
                        {
                            if ((middleValueHigh < getSeriesData.High[bar - i]))
                            {
                                up = false;
                                break;
                            }
                        }
                        if (up)
                        {
                            Result[middleIndexHigh] = middleValueHigh;

                            if(drawSwingHighs)
                            { 
                                var drawSwingHigh = Chart.DrawIcon(iconName + middleIndexHigh.ToString(), ChartIconType.DownArrow, middleIndexHigh, middleValueHigh, Color.Blue);
                            }
                        }
                    }
                }
                return Result;
            }
            catch (Exception error)
            {
                Print("zziGetAndDrawSwingHighs Method Error: ", error.ToString());
                return Result;
            }
        }

I execute method from cBot

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        public IndicatorBuildingBlocks ibb;



        protected override void OnStart()
        {
            ibb = Indicators.GetIndicator<IndicatorBuildingBlocks>();
        }

        protected override void OnTick()
        {
            ibb.zziGetAndDrawSwingHighs();
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

By doing this, I can now Get the data and it will draw it on the chart automatically when calling the method. (See Below).

However, if you want to use the same concept to automatically draw and get the data from the indicator and the indicator is something like an SMA, where you need to draw a line between two points mapped on the chart, the solution on the indicator side is to use Plotype.Line in combination with the Output attribute.  What would you do in this case?  IE is there something that can replace this Plotype.Line functionality.

Thank you for your help.


@myinvestmentsfx

myinvestmentsfx
24 Aug 2018, 08:56

RE:

myinvestmentsfx said:

Thank you Panagiotis,  appriciate the help. I've download the platform directly from Spotware and have all the methods now.

How would you access the FibonacciLevel Values of the one you just drawed?

            var drawFibo = Chart.DrawFibonacciRetracement("test", startIndex, startValue, stopIndex, stopValue, "Black", 1, LineStyle.LinesDots);
            var myDictionary = drawFibo.FibonacciLevels.ToDictionary(????)

Kind Regards,

Just to be clear, i'm look for the prices that corresponds with the fibonannci % level. 

I know it's possible to {get; set:) percentage level as per below.  But how do I get the corresponding price that maps to the percetage level?  I'm assuming this should be available since the calculation is done in the background to display it on the chart. 

            var drawFibo = Chart.DrawFibonacciRetracement("test", startIndex, startValue, stopIndex, stopValue, "Black", 1, LineStyle.LinesDots);
            var x = drawFibo.FibonacciLevels[0];
            var y = x.PercentLevel = 20;
            var z = drawFibo.DisplayPrices = true;


@myinvestmentsfx

myinvestmentsfx
23 Aug 2018, 18:38

Thank you Panagiotis,  appriciate the help. I've download the platform directly from Spotware and have all the methods now.

How would you access the FibonacciLevel Values of the one you just drawed?

            var drawFibo = Chart.DrawFibonacciRetracement("test", startIndex, startValue, stopIndex, stopValue, "Black", 1, LineStyle.LinesDots);
            var myDictionary = drawFibo.FibonacciLevels.ToDictionary(????)

Kind Regards,


@myinvestmentsfx

myinvestmentsfx
23 Aug 2018, 12:05 ( Updated at: 21 Dec 2023, 09:20 )

RE:

Panagiotis Charalampous said:

Hi myinvestmentsfx,

See below an example

Chart.DrawFibonacciRetracement("Example", Server.Time, 1.14, Server.Time.AddDays(-1), 1.16, Color.Red);

Best Regards,

Panagiotis

Hi Panagiotis,

The method doesn't seem to exist under Chart?


@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

myinvestmentsfx
15 Aug 2018, 07:48

Hi .ics,

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

Kind Regards,


@myinvestmentsfx

myinvestmentsfx
17 Nov 2017, 09:23

Hi Guys,

Anyone else in the community that can help with this?  Doesn't seem like Spotware has an answer for us?

Kind Regards,

myinvestmentsfx


@myinvestmentsfx

myinvestmentsfx
15 Nov 2017, 10:28

RE: RE: RE:

myinvestmentsfx said:

myinvestmentsfx said:

Panagiotis Charalampous said:

Hi myinvestmentsfx,

The product team is looking into it. I will update you as soon as I get their feedback.

Best Regards,

Panagiotis

Hi Panagiotis,

I assume your product team doesn't work over the weekend?

Kind Regards,

myinvestmentsfx

Hi Panagiotis,

Do you think we will receive some feedback from the product team today by any chance?

Kind Regards,

myinvestmentsfx

Hi Panagiotis,

Still nothing?

Kind Regards,

myinvestmentsfx


@myinvestmentsfx

myinvestmentsfx
13 Nov 2017, 10:46

RE: RE:

myinvestmentsfx said:

Panagiotis Charalampous said:

Hi myinvestmentsfx,

The product team is looking into it. I will update you as soon as I get their feedback.

Best Regards,

Panagiotis

Hi Panagiotis,

I assume your product team doesn't work over the weekend?

Kind Regards,

myinvestmentsfx

Hi Panagiotis,

Do you think we will receive some feedback from the product team today by any chance?

Kind Regards,

myinvestmentsfx


@myinvestmentsfx

myinvestmentsfx
11 Nov 2017, 18:31

RE:

Panagiotis Charalampous said:

Hi myinvestmentsfx,

The product team is looking into it. I will update you as soon as I get their feedback.

Best Regards,

Panagiotis

Hi Panagiotis,

I assume your product team doesn't work over the weekend?

Kind Regards,

myinvestmentsfx


@myinvestmentsfx

myinvestmentsfx
10 Nov 2017, 13:07 ( Updated at: 21 Dec 2023, 09:20 )

RE:

Panagiotis Charalampous said:

Hi myinvestmentsfx,

The product team is looking into it. I will update you as soon as I get their feedback.

Best Regards,

Panagiotis

Thank you, much appriciated.  i've also asked another developer to look at the code and they tried using old school multithreading techniques.  cAlgo crashes and they get the error below.  Same error I go using Parallel loop.  See code below.

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

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        [Output("Main")]
        public IndicatorDataSeries Result { get; set; }

        ///////////////////////////////////////////////////////////////////////////////////////////////////
        //                       Illustration Purposes
        //   Goal is to do get the lows of multiple symbols in a specified timeframe at the same time
        //   
        ///////////////////////////////////////////////////////////////////////////////////////////////////


        protected override void Initialize()
        {
            ///////////////////////////////////////////////////////////////////////////////////////////////////
            //                       Attempt 1
            //   Calling MarketData.GetSeries & MarketSeries works fine together, 
            //   however 2 x MarketData.GetSeries calls Kicking off at the same time seems to be a problem.
            //   Uncomment below to run.
            ///////////////////////////////////////////////////////////////////////////////////////////////////

            // Attempt1_GetSymbolCodeLowAsyncWithTasks();

            ///////////////////////////////////////////////////////////////////////////////////////////////////
            //                       Attempt 2
            //   Parallel Foreach loop work fine with doing normal calculation
            //   If same logic is applied but trying to get lows of multiple symbols, we run into a problem.
            //   Uncomment below to run.
            ///////////////////////////////////////////////////////////////////////////////////////////////////        

            // Attempt_2_ParallelGetLows(AllSymbolCodes());

            ///////////////////////////////////////////////////////////////////////////////////////////////////
            //                       Attempt 3
            //   Old school multithreading.
            //   Uncomment below to run.
            ///////////////////////////////////////////////////////////////////////////////////////////////////  

            test();

        }

        public override void Calculate(int index)
        {
            // Calculate value at specified index
            // Result[index] = ...
        }
        public void Attempt1_GetSymbolCodeLowAsyncWithTasks()
        {
            var t1 = Task.Factory.StartNew(() => EURUSD());
            var t2 = Task.Factory.StartNew(() => GBPUSD());
            var t3 = Task.Factory.StartNew(() => USDCHF());
            var t4 = Task.Factory.StartNew(() => USDJPY());
        }

        public double EURUSD()
        {
            Print("API Call 1 Kicking Off");
            double result = (MarketData.GetSeries(MarketData.GetSymbol("EURUSD"), TimeFrame.Daily).Low.Last(0));
            Print("API Call 1 EURUSD Low Result: ", result);
            return result;
        }

        public void EURUSD2()
        {
            Print("API Call 1 Kicking Off");
            double result = (MarketData.GetSeries(MarketData.GetSymbol("EURUSD"), TimeFrame.Daily).Low.Last(0));
            Print("API Call 1 EURUSD Low Result: ", result);
            // return result;
        }
        public string GBPUSD()
        {
            Print("API Call 2 Kicking Off (Different API) ");
            string result = (MarketSeries.SymbolCode);
            Print("API Call 2 Get Symbol Code Result: ", result);
            return result;
        }
        public double USDCHF()
        {
            Print("Kicking off API Call 3");
            double result = (MarketData.GetSeries(MarketData.GetSymbol("USDCHF"), TimeFrame.Daily).Open.Last(0));
            Print("API Call 3 Get USDCHF Open Result: ", result);
            return result;
        }

        public void USDCHF2()
        {
            Print("Kicking off API Call 3");
            double result = (MarketData.GetSeries(MarketData.GetSymbol("USDCHF"), TimeFrame.Daily).Open.Last(0));
            Print("API Call 3 Get USDCHF Open Result: ", result);
            // return result;
        }
        public double USDJPY()
        {
            Print("Kicking off API Call 4");
            double result = (MarketData.GetSeries(MarketData.GetSymbol("USDJPY"), TimeFrame.Daily).Close.Last(0));
            Print("API Call 4 Get USDJPY Close Result: ", result);
            return result;
        }


        public void USDJPY2()
        {
            Print("Kicking off API Call 4");
            double result = (MarketData.GetSeries(MarketData.GetSymbol("USDJPY"), TimeFrame.Daily).Close.Last(0));
            Print("API Call 4 Get USDJPY Close Result: ", result);
            // return result;
        }


        public ConcurrentBag<Symbol> AllSymbolCodes()
        {
            ConcurrentBag<Symbol> allSymbolCodes = new ConcurrentBag<Symbol> 
            {
                MarketData.GetSymbol("EURUSD"),
                MarketData.GetSymbol("GBPUSD"),
                MarketData.GetSymbol("USDCHF"),
                MarketData.GetSymbol("USDJPY"),
                MarketData.GetSymbol("USDCAD"),
                MarketData.GetSymbol("AUDUSD"),
                MarketData.GetSymbol("GBPJPY"),
                MarketData.GetSymbol("EURJPY"),
                MarketData.GetSymbol("NZDUSD"),
                MarketData.GetSymbol("AUDJPY")
            };
            return allSymbolCodes;
        }

        public void test()
        {
            try
            {
                ThreadStart threadactionJPN = new ThreadStart(USDJPY2);
                var threadJPN = new Thread(threadactionJPN);
                threadJPN.Start();

                ThreadStart threadactionEUR = new ThreadStart(EURUSD2);
                var threadEUR = new Thread(threadactionEUR);
                threadEUR.Start();

                ThreadStart threadactionCHF = new ThreadStart(USDCHF2);
                var threadCHF = new Thread(threadactionCHF);
                threadCHF.Start();
            } catch (Exception ex)
            {
                Debug.WriteLine("{0} Exception caught.", ex);
            }

        }
        public ConcurrentBag<double> Attempt_2_ParallelGetLows(ConcurrentBag<Symbol> allSymbolCodes)
        {
            var StartTime = Server.Time;
            ConcurrentBag<double> allSymbolCodesDaily = new ConcurrentBag<double>();

            //Get lows of multiple symbols using Parallel For Loop, doesn't seem to work.

            Print("Starting Parralel Loop Get Lows...");

            Parallel.ForEach(allSymbolCodes, (Symbol i) =>
            {
                try
                {
                    var x = (MarketData.GetSeries(i, TimeFrame.Daily));
                    try
                    {
                        double result = x.Low.Last(0);

                        try
                        {
                            allSymbolCodesDaily.Add(result);
                        } catch (Exception a)
                        {
                            Print("Problem occurred adding to list", a);
                        }
                    } catch (Exception b)
                    {
                        Print("Problem occured with getting low", b);
                    }
                } catch (Exception c)
                {
                    Debug.WriteLine("{0} Exception caught.", c);
                }

            });
            Print("Ending Parralel Loop Get Lows...");
            Print(string.Join(",", allSymbolCodesDaily));

            return (allSymbolCodesDaily);
        }
    }
}

Error Message Below.

.


@myinvestmentsfx

myinvestmentsfx
10 Nov 2017, 12:08

RE:

Panagiotis Charalampous said:

Hi myinvestmentsfx,

Multithreading in general was not and is not a problem for cAlgo. The discussion you posted inquires whether cAlgo application itself is multithreaded, more specifically if it runs the bots on separate threads than the main application, causing synchronization issues. The answer to this question is no, cAlgo is not running cBots in separate threads, except the Timer class, therefore there should not be any synchronization issues.

However, this does not mean that you cannot use multithreading techniques within your cBot. As long as your programming techniques are correct, then you should not experience any problems. If you want, you can post the issues you face one by one and we can discuss them.

Best Regards,

Panagiotis

Hi Panagiotis,

Any update on the information, testing and debug results I posted?

Kind Regards,

myinvestmentsfx


@myinvestmentsfx

myinvestmentsfx
09 Nov 2017, 22:57 ( Updated at: 21 Dec 2023, 09:20 )

After some try and catch, debugging etc.  I found this?  Any ideas what it means?

Kind Regards,

myinvestmentsfx


@myinvestmentsfx

myinvestmentsfx
09 Nov 2017, 15:54 ( Updated at: 21 Dec 2023, 09:20 )

Hi Panagiotis,

Ok, not a problem.  Please see the code used to test the various scenarios.

Attempt 1 and 2 can be run by commenting out one of the two under initialize.

  Test Results below,

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

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewIndicator : Indicator
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        [Output("Main")]
        public IndicatorDataSeries Result { get; set; }

        ///////////////////////////////////////////////////////////////////////////////////////////////////
        //                       Illustration Purposes
        //   Goal is to get the lows of multiple symbols in a specified timeframe at the same time
        //   
        ///////////////////////////////////////////////////////////////////////////////////////////////////


        protected override void Initialize()
        {
            ///////////////////////////////////////////////////////////////////////////////////////////////////
            //                       Attempt 1
            //   Calling MarketData.GetSeries & MarketSeries works fine together, 
            //   however 2 x MarketData.GetSeries calls Kicking off at the same time seems to be a problem.
            //   Uncomment below to run.
            ///////////////////////////////////////////////////////////////////////////////////////////////////

            // Attempt1_GetSymbolCodeLowAsyncWithTasks();

            ///////////////////////////////////////////////////////////////////////////////////////////////////
            //                       Attempt 2
            //   Parallel Foreach loop work fine with doing dummy calculation
            //   If same logic is applied but trying to get lows of multiple symbols, we run into a problem.
            //   Uncomment below to run.
            ///////////////////////////////////////////////////////////////////////////////////////////////////        

            Attempt_2_ParallelGetLows(AllSymbolCodes());
        }

        public override void Calculate(int index)
        {
            // Calculate value at specified index
            // Result[index] = ...
        }
        public void Attempt1_GetSymbolCodeLowAsyncWithTasks()
        {
            var t1 = Task.Factory.StartNew(() => EURUSD());
            var t2 = Task.Factory.StartNew(() => GBPUSD());
            var t3 = Task.Factory.StartNew(() => USDCHF());
            var t4 = Task.Factory.StartNew(() => USDJPY());
        }

        public double EURUSD()
        {
            Print("API Call 1 Kicking Off");
            double result = (MarketData.GetSeries(MarketData.GetSymbol("EURUSD"), TimeFrame.Daily).Low.Last(0));
            Print("API Call 1 EURUSD Low Result: ", result);
            return result;
        }
        public string GBPUSD()
        {
            Print("API Call 2 Kicking Off (Different API) ");
            string result = (MarketSeries.SymbolCode);
            Print("API Call 2 Get Symbol Code Result: ", result);
            return result;
        }
        public double USDCHF()
        {
            Print("Kicking off API Call 3");
            double result = (MarketData.GetSeries(MarketData.GetSymbol("USDCHF"), TimeFrame.Daily).Open.Last(0));
            Print("API Call 3 Get USDCHF Open Result: ", result);
            return result;
        }
        public double USDJPY()
        {
            Print("Kicking off API Call 4");
            double result = (MarketData.GetSeries(MarketData.GetSymbol("USDJPY"), TimeFrame.Daily).Close.Last(0));
            Print("API Call 4 Get USDJPY Close Result: ", result);
            return result;
        }


        public List<Symbol> AllSymbolCodes()
        {
            List<Symbol> allSymbolCodes = new List<Symbol> 
            {
                MarketData.GetSymbol("EURUSD"),
                MarketData.GetSymbol("GBPUSD"),
                MarketData.GetSymbol("USDCHF"),
                MarketData.GetSymbol("USDJPY"),
                MarketData.GetSymbol("USDCAD"),
                MarketData.GetSymbol("AUDUSD"),
                MarketData.GetSymbol("GBPJPY"),
                MarketData.GetSymbol("EURJPY"),
                MarketData.GetSymbol("NZDUSD"),
                MarketData.GetSymbol("AUDJPY")
            };
            return allSymbolCodes;
        }
        public ConcurrentBag<double> Attempt_2_ParallelGetLows(List<Symbol> allSymbolCodes)
        {
            var StartTime = Server.Time;
            ConcurrentBag<double> allSymbolCodesDaily = new ConcurrentBag<double>();

            Print("Starting Parallel Loop Testing ...");
            ConcurrentBag<double> TestParallel = new ConcurrentBag<double> 
            {
                1.1,
                2.2,
                3.3,
                4.4,
                5.5,
                6.6,
                7.7,
                8.8
            };
            ConcurrentBag<double> TestParallel2 = new ConcurrentBag<double>();

            //Testing Parallel For Loop with dummy data, seems to work fine.

            Parallel.ForEach(TestParallel, (double t) =>
            {
                double result = 5 * t;
                TestParallel2.Add(result);
            });
            Print("Ending Parralel Loop Test...");
            Print("Test Loop Results: ", string.Join(",", TestParallel2));

            //Get lows of multiple symbols using Parallel For Loop, doesn't seem to work.

            Print("Starting Parralel Loop Get Lows...");
            Parallel.ForEach(allSymbolCodes, (Symbol i) =>
            {
                double result = (MarketData.GetSeries(i, TimeFrame.Daily).Low.Last(0));
                allSymbolCodesDaily.Add(result);
            });
            Print("Ending Parralel Loop Get Lows...");
            Print(string.Join(",", allSymbolCodesDaily));

            return (allSymbolCodesDaily);
        }
    }
}

Result of Attempt 2 - The Get Lows Parallel Loop Never Finish

Attempt 1 - Call 3 & 4 never completes (Same type of API call as the first one)


@myinvestmentsfx

myinvestmentsfx
09 Nov 2017, 13:01 ( Updated at: 21 Dec 2023, 09:20 )

RE:

Panagiotis Charalampous said:

Hi guys,

Indeed cAlgo works with .Net Framework 4.0 for compatibility reasons. We will upgrade the framework in a later version.

Best Regards,

Panagiotis

Hi Panagiotis,

Thank you for the update,

Is multi threading still as problem for the cAglo API?  I've tried various multi-threading techniques and all seem to be having endless problems.

-Async and Await

-Parralel For Loops

-Kicking of various tasks

All of them seem to be a problem.  I suspect it being related to the thread below?

Kind Regards,

 


@myinvestmentsfx

myinvestmentsfx
08 Nov 2017, 21:50

RE:

Paul_Hayes said:

ok, that makes sense. 

I noticed that you have no exception-handling in the code, one mistake and it could make the platform crash, especially as you are using threaded tasks.

You need to add try's and catches to each block of code as well as debug the code from the start so that when you add an instance it starts debugging each line of code if you do this you will find your error.

Thank you Paul, i will do that and see what I can find.  Appriciate the guidance.

Kind Regards,


@myinvestmentsfx

myinvestmentsfx
08 Nov 2017, 21:16 ( Updated at: 21 Dec 2023, 09:20 )

RE:

Paul_Hayes said:

Hi,

Your code gives this error when you attempt to build it in cAlgo

Error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.

Build errors in Visual Studio

The link below will tell you how to fix it.

https://stackoverflow.com/questions/11836325/await-operator-can-only-be-used-within-an-async-method

 

Paul Hayes
Sales & Marketing
Emailcontact@clickalgo.com
Phone: (44) 203 289 6573
Websitehttps://clickalgo.com

Hi Paul,

Thank you for this, it's much appriciated. However it still seems that the problem is related to the .Net Framework rather than the actual code.  If you change project to use .Net Framework 4.6.2, then it's builds without any errors in visual studio.  If I then add an instance to the indicator in cAlgo, cAglo crashes.  See screenshot of sucessful build.

Sucessful Build


@myinvestmentsfx